inital commit

This commit is contained in:
2026-06-19 20:08:01 +06:00
commit 8a5abeeae4
13128 changed files with 3192007 additions and 0 deletions

View File

@@ -0,0 +1,643 @@
<?php
/**
* MyBB 1.8
* Copyright 2014 MyBB Group, All Rights Reserved
*
* Website: http://www.mybb.com
* License: http://www.mybb.com/about/license
*
*/
// Disallow direct access to this file for security reasons
if(!defined("IN_MYBB"))
{
die("Direct initialization of this file is not allowed.<br /><br />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(is_array($event['repeats']['days']) && 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;
}
}

View File

@@ -0,0 +1,8 @@
<html>
<head>
<title></title>
</head>
<body>
&nbsp;
</body>
</html>

View File

@@ -0,0 +1,340 @@
<?php
/**
* MyBB 1.8
* Copyright 2014 MyBB Group, All Rights Reserved
*
* Website: http://www.mybb.com
* License: http://www.mybb.com/about/license
*
*/
// Disallow direct access to this file for security reasons
if(!defined("IN_MYBB"))
{
die("Direct initialization of this file is not allowed.<br /><br />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 && $this->login_data['uid'] != 0)
{
$logins = login_attempt_check($this->login_data['uid'], 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, "lax");
if($this->captcha !== false)
{
$this->captcha->invalidate_captcha();
}
$plugins->run_hooks('datahandler_login_complete_end', $this);
return true;
}
}

View File

@@ -0,0 +1,772 @@
<?php
/**
* MyBB 1.8
* Copyright 2014 MyBB Group, All Rights Reserved
*
* Website: http://www.mybb.com
* License: http://www.mybb.com/about/license
*
*/
// Disallow direct access to this file for security reasons
if(!defined("IN_MYBB"))
{
die("Direct initialization of this file is not allowed.<br /><br />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;
}
// If the length of message is beyond SQL limitation for 'text' field
else if(strlen($message) > 65535)
{
$this->set_error("message_too_long", array('65535', strlen($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(empty($pm['saveasdraft']) && $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'] && $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);
$this->pmid = $db->insert_query("privatemessages", $this->pm_insert_data);
$plugins->run_hooks("datahandler_pm_insert_updatedraft_commit", $this);
// 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);
$plugins->run_hooks("datahandler_pm_insert_commit", $this);
// 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']) && is_array($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);
$plugins->run_hooks("datahandler_pm_insert_savedcopy_commit", $this);
// 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;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,741 @@
<?php
/**
* MyBB 1.8
* Copyright 2014 MyBB Group, All Rights Reserved
*
* Website: http://www.mybb.com
* License: http://www.mybb.com/about/license
*
*/
// Disallow direct access to this file for security reasons
if(!defined("IN_MYBB"))
{
die("Direct initialization of this file is not allowed.<br /><br />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 2;
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;
}
}