website_jukni/forum/Packages/subbacount/SubAccount.php
2017-12-29 15:51:59 +01:00

1452 lines
No EOL
47 KiB
PHP

<?php
/**********************************************************************************
* SubAccount.php *
***********************************************************************************
* Software Version: 1.0.0 *
* Copyright 2008-2009 by: Matt Zuba (http://www.mattzuba.com) *
***********************************************************************************
* This mod is free software; you can not redistribute it *
* *
* This mod is distributed in the hope that it is and will be useful, but *
* WITHOUT ANY WARRANTIES; without even any implied warranty of MERCHANTABILITY *
* or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* The latest version can always be found at http://www.mattzuba.com. *
**********************************************************************************/
if (!defined('SMF'))
die('Hacking attempt...');
/* This file has the primary job of showing and editing people's subaccounts.
void SubAccountBrowse(int id_member)
// !!!
void SubAccountCreate(int id_member)
// !!!
void SubAccountDelete(int id_member)
// !!!
void SubAccountMerge(int id_member)
// !!!
void SubAccountSplit(int id_member)
// !!!
void SwitchSubAccount()
// !!!
*/
function SubAccountBrowse($memID)
{
global $context, $txt, $cur_profile, $smcFunc, $memberContext;
$context['sub_template'] = 'manage_subaccounts';
$context['page_desc'] = $txt['modifysubaccounts_desc'];
$loaded_ids = !empty($cur_profile['subaccounts']) ? array_unique(loadMemberData(array_keys($cur_profile['subaccounts']))) : array();
// Need to get the PM info for the subaccounts too
if (!empty($loaded_ids))
{
$request = $smcFunc['db_query']('', '
SELECT id_member, instant_messages, unread_messages
FROM {db_prefix}members
WHERE id_member in ({array_int:subaccounts})',
array(
'subaccounts' => $loaded_ids,
)
);
$pms = array();
while ($row = $smcFunc['db_fetch_assoc']($request))
$pms[$row['id_member']] = array(
'total' => $row['instant_messages'],
'unread' => $row['unread_messages'],
);
$smcFunc['db_free_result']($request);
// Setup the array
foreach ($loaded_ids as $id)
{
if (loadMemberContext($id))
{
$context['subaccounts'][] = array(
'id' => $id,
'name' => $memberContext[$id]['name'],
'href' => $memberContext[$id]['href'],
'group' => !empty($memberContext[$id]['group']) ? $memberContext[$id]['group'] : $memberContext[$id]['post_group'],
'stars' => $memberContext[$id]['group_stars'],
'posts' => $memberContext[$id]['posts'],
'messages' => $pms[$id],
'chatters' => array(
'icq' => $memberContext[$id]['icq']['link'],
'aim' => $memberContext[$id]['aim']['link'],
'yim' => $memberContext[$id]['yim']['link'],
'msn' => $memberContext[$id]['msn']['link'],
),
'website' => $memberContext[$id]['website'],
'permissions' => array(
'can_delete' => $context['can_delete'],
'can_merge' => $context['can_merge'] && (empty($memberContext[$id]['is_shareable']) || $memberContext[$id]['is_shareable'] == $cur_profile['id_member']),
'can_split' => $context['can_split'] && (empty($memberContext[$id]['is_shareable']) || $memberContext[$id]['is_shareable'] == $cur_profile['id_member']),
'can_reassign' => $context['can_reassign'] && (empty($memberContext[$id]['is_shareable']) || $memberContext[$id]['is_shareable'] == $cur_profile['id_member']),
'can_share' => $context['can_create'] && (empty($memberContext[$id]['is_shareable']) || $memberContext[$id]['is_shareable'] == $cur_profile['id_member']),
),
'is_shared' => !empty($memberContext[$id]['is_shareable']),
);
}
}
}
}
function SubAccountCreate($memID)
{
global $context, $smcFunc, $txt, $sourcedir, $user_info, $cur_profile, $modSettings;
$context['sub_template'] = 'manage_subaccounts_create';
if (empty($cur_profile['additional_groups']))
$user_groups = array($cur_profile['id_group'], $cur_profile['id_post_group']);
else
$user_groups = array_merge(
array($cur_profile['id_group'], $cur_profile['id_post_group']),
explode(',', $cur_profile['additional_groups'])
);
$context['member']['is_admin'] = in_array(1, $user_groups);
if (isset($_REQUEST['make_shared']))
{
if (empty($_GET['subaccount']))
{
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['subaccount_not_selected'];
return SubAccountBrowse($memID);
}
$subaccount = (int) $_GET['subaccount'];
// Let's do some checks first.
// If this is a subaccount, it shouldn't even have subaccounts, but you never know...
if (!empty($cur_profile['id_parent']) || !array_key_exists($subaccount, $cur_profile['subaccounts']) || (!empty($cur_profile['subaccounts'][$subaccount]['shareable']) && ($cur_profile['subaccounts'][$subaccount]['shareable'] != $cur_profile['id_member'] || !$context['member']['is_admin'])))
fatal_lang_error('cannot_subaccounts_create_own', false);
if (!empty($cur_profile['subaccounts'][$subaccount]['shareable']))
{
$request = $smcFunc['db_query']('', '
SELECT id_parent
FROM {db_prefix}subaccounts
WHERE id_member = {int:subaccount}
AND id_parent != {int:parent}',
array(
'subaccount' => $subaccount,
'parent' => $cur_profile['id_member'],
)
);
$deleteUsers = array();
while ($row = $smcFunc['db_fetch_assoc']($request))
$deleteUsers[] = $row['id_parent'];
if (!empty($deleteUsers))
{
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_parent IN ({array_int:members})
AND id_member = {int:subaccount}',
array(
'members' => $deleteUsers,
'subaccount' => $subaccount,
)
);
foreach ($deleteUsers as $id)
cache_put_data('user_subaccounts-' . $id, null, 240);
}
updateMemberData($subaccount, array('is_shareable' => 0));
}
else
updateMemberData($subaccount, array('is_shareable' => $cur_profile['id_member']));
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
elseif (isset($_POST['submit']))
{
// Make sure they came from *somewhere*, have a session.
checkSession();
foreach ($_POST as $key => $value) {
if (!is_array($_POST[$key]))
$_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key]));
}
$username = !empty($_POST['username']) ? $_POST['username'] : '';
require_once($sourcedir . '/Subs-Members.php');
// Is this an existing member??
$request = $smcFunc['db_query']('', '
SELECT mem.id_member, mem.passwd, mem.member_name, IFNULL(sub.id_parent, 0) as is_subaccount, mem.is_shareable
FROM {db_prefix}members AS mem
LEFT JOIN {db_prefix}subaccounts AS sub ON (sub.id_member = mem.id_member)
WHERE ' . ($smcFunc['db_case_sensitive'] ? 'LOWER(member_name)' : 'member_name') . ' = {string:user_name}
LIMIT 1',
array(
'user_name' => $smcFunc['db_case_sensitive'] ? strtolower($username) : $username,
)
);
if ($member = $smcFunc['db_fetch_assoc']($request))
{
// If the member found is the one this profile belongs to, die out...
if ($member['id_member'] == $cur_profile['id_member'] || (!empty($member['is_subaccount']) && (empty($member['is_shareable']) || $member['is_subaccount'] == $cur_profile['id_member'])))
{
loadLanguage('Errors');
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = 'name_taken';
return;
}
// Lets see if they got the password right...
$passwd = sha1(strtolower($member['member_name']) . (!empty($_POST['passwrd1']) ? un_htmlspecialchars($_POST['passwrd1']) : ''));
// Looks like they're smart enough to have this. Now we need to get any subaccounts that the new subaccount might
// already have and convert them...
if ($member['passwd'] == $passwd)
{
// Let's see if it has any existing aliases
$request = $smcFunc['db_query']('', '
SELECT sub.id_member, mem.is_shareable
FROM {db_prefix}subaccounts AS sub
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = sub.id_member)
WHERE sub.id_parent = {int:parent}',
array(
'parent' => $member['id_member'],
)
);
$changeUsers = array();
$sharedUsers = array();
$createdSharedUsers = array();
while ($row = $smcFunc['db_fetch_assoc']($request))
{
// If the current subaccount is a shared account, and it wasn't created by the parent we're merging here, add it
// to an array so we don't udpate it's email address
if (!empty($row['is_shareable']) && $row['is_shareable'] != $member['id_member'])
$sharedUsers[] = $row['id_member'];
elseif (!empty($row['is_shareable']) && $row['is_shareable'] == $member['id_member'])
$createdSharedUsers[] = $row['id_member'];
$changeUsers[] = $row['id_member'];
}
$smcFunc['db_free_result']($request);
// Let's check the table for any possible subaccounts that would be linked, that already are and delete them
if (!empty($changeUsers))
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_member IN ({array_int:changeusers})
AND id_parent = {int:new_parent}',
array(
'changeusers' => $changeUsers,
'new_parent' => $cur_profile['id_member'],
)
);
// Update any accounts linked to the one we're really linking up
$smcFunc['db_query']('', '
UPDATE {db_prefix}subaccounts
SET id_parent = {int:new_parent}
WHERE id_parent = {int:old_parent}',
array(
'new_parent' => $cur_profile['id_member'],
'old_parent' => $member['id_member'],
)
);
// Add our current user
$changeUsers[] = $member['id_member'];
// Change all subaccounts except those that are shared and not owned to have this profiles email address
updateMemberData(array_diff($changeUsers, $sharedUsers), array('email_address' => $cur_profile['email_address']));
// If there are any shared aliases created by the mergee, update them to be owned by the new owner
if (!empty($createdSharedUsers))
updateMemberData($createdSharedUsers, array('is_shareable' => $cur_profile['id_member']));
// Finally add the member to the subaccounts table
$smcFunc['db_insert']('',
'{db_prefix}subaccounts',
array('id_member' => 'int', 'id_parent' => 'int'),
array($member['id_member'], $cur_profile['id_member']),
array('id_parent')
);
// Delete the cache for this member
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
// Sorry, you lose...
else
{
loadLanguage('Errors');
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = 'bad_password';
return;
}
}
$smcFunc['db_free_result']($request);
// Set the options needed for registration.
$regOptions = array(
'interface' => '',
'username' => $username,
// Create a fake email address just to pass validation, it'll get changed automagically with the extra_register_vars array.
'email' => substr(preg_replace('/\W/', '', md5(rand())), 0, 4).'@'.substr(preg_replace('/\W/', '', md5(rand())), 0, 5).'.com',
'password' => !empty($_POST['passwrd1']) ? un_htmlspecialchars($_POST['passwrd1']) : '',
'password_check' => !empty($_POST['passwrd2']) ? un_htmlspecialchars($_POST['passwrd2']) : '',
'openid' => '',
'auth_method' => 'password',
'check_reserved_name' => true,
'check_password_strength' => true,
'check_email_ban' => false,
'send_welcome_email' => '',
'require' => 'nothing',
'theme_vars' => array(),
'memberGroup' => !empty($modSettings['subaccountsInheritParentGroup']) ? $cur_profile['id_group'] : 0,
'extra_register_vars' => array(
'email_address' => $cur_profile['email_address'],
'warning' => $cur_profile['warning'],
'hide_email' => $cur_profile['hide_email'],
'time_offset' => $cur_profile['time_offset'],
'lngfile' => $cur_profile['lngfile'],
),
);
foreach ($cur_profile['options'] as $var => $value)
$regOptions['theme_vars'][$var] = $value;
$memberID = registerMember($regOptions, true);
// Was there actually an error of some kind dear boy?
if (is_array($memberID)) {
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'] = $memberID;
return;
}
// Finally add the member to the subaccounts table
$smcFunc['db_insert']('',
'{db_prefix}subaccounts',
array('id_member' => 'int', 'id_parent' => 'int'),
array($memberID, $cur_profile['id_member']),
array('id_parent')
);
// Delete the Cache for this user
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
}
function SubAccountDelete($memID)
{
global $sourcedir, $modSettings, $user_info, $smcFunc, $txt, $context, $cur_profile;
// Make sure they came from *somewhere*, have a session.
checkSession('get');
if (empty($_GET['subaccount']))
{
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['subaccount_not_selected'];
return SubAccountBrowse($memID);
}
$subaccount = (int) $_GET['subaccount'];
// Let's do some checks first.
// If this is an subaccount, it shouldn't even have subaccounts, but you never know...
if (!empty($cur_profile['id_parent']) || !array_key_exists($subaccount, $cur_profile['subaccounts']))
fatal_lang_error('cannot_delete_subaccount', false);
// Get their name for logging purposes.
$request = $smcFunc['db_query']('', '
SELECT id_member, member_name, CASE WHEN id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 THEN 1 ELSE 0 END AS is_admin
FROM {db_prefix}members
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
'admin_group' => 1,
)
);
$row = $smcFunc['db_fetch_assoc']($request);
$smcFunc['db_free_result']($request);
// Make sure they aren't trying to delete administrators if they aren't one. But don't bother checking if it's just themself.
// Just a small check to make sure that the board will never loose their only admin this way
if (!empty($row['is_admin']) && !allowedTo('admin_forum'))
fatal_lang_error('cannot_delete_subaccount', false);
// Log the action - regardless of who is deleting it.
if (!empty($modSettings['modlog_enabled']))
{
$log_inserts = array();
// Add it to both the moderation and admin logs as it effects both.
$log_inserts[] = array(
time(), 3, $user_info['id'], $user_info['ip'], 'delete_subaccount',
0, 0, 0, serialize(array('member' => $row['id_member'], 'name' => $row['member_name'], 'parent' => $cur_profile['member_name'])),
);
$log_inserts[] = array(
time(), 1, $user_info['id'], $user_info['ip'], 'delete_subaccount',
0, 0, 0, serialize(array('member' => $row['id_member'], 'name' => $row['member_name'], 'parent' => $cur_profile['member_name'])),
);
// Do the actual logging.
$smcFunc['db_insert']('',
'{db_prefix}log_actions',
array(
'log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string',
'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534',
),
$log_inserts,
array('id_action')
);
}
// If they don't own this sharable id, but don't want it, just remove it as a link in the table
if (!empty($cur_profile['subaccounts'][$subaccount]['shareable']) && $cur_profile['id_member'] != $cur_profile['subaccounts'][$subaccount]['shareable'])
{
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_member = {int:user}
AND id_parent = {int:parent}',
array(
'user' => $subaccount,
'parent' => $cur_profile['id_member'],
)
);
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
// Integration rocks!
if (isset($modSettings['integrate_delete_member']) && function_exists($modSettings['integrate_delete_member']))
call_user_func($modSettings['integrate_delete_member'], $row['id_member']);
// Remove them from the subaccounts table
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Convert their posts to the parent id and name
$smcFunc['db_query']('', '
UPDATE {db_prefix}messages
SET id_member = {int:parent_id}, poster_name = {string:parent_name}
WHERE id_member = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'parent_name' => $cur_profile['real_name'],
'user' => $subaccount,
)
);
$messageCount = $smcFunc['db_affected_rows']();
$smcFunc['db_query']('', '
UPDATE {db_prefix}polls
SET id_member = {int:parent_id}, poster_name = {string:parent_name}
WHERE id_member = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'parent_name' => $cur_profile['real_name'],
'user' => $subaccount,
)
);
// Make these peoples' posts guest first posts and last posts.
$smcFunc['db_query']('', '
UPDATE {db_prefix}topics
SET id_member_started = {int:parent_id}
WHERE id_member_started = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}topics
SET id_member_updated = {int:parent_id}
WHERE id_member_updated = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_actions
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
// Delete the bans
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_banned
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_errors
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
// Delete the member.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}members
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Delete the logs...
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_actions
WHERE id_log = {int:log_type}
AND id_member = {int:user}',
array(
'log_type' => 2,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_boards
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_group_requests
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_karma
WHERE id_target = {int:user}
OR id_executor = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_mark_read
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_notify
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_online
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_topics
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}collapsed_categories
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Make their votes appear as their parent's votes - at least it keeps the totals right.
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_polls
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
// Delete personal messages.
require_once($sourcedir . '/PersonalMessage.php');
deleteMessages(null, null, $subaccount);
$smcFunc['db_query']('', '
UPDATE {db_prefix}personal_messages
SET id_member_from = {int:parent_id}
WHERE id_member_from = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
// Delete avatar.
require_once($sourcedir . '/ManageAttachments.php');
removeAttachments(array('id_member' => $subaccount));
// Update Attachment Ownership
$smcFunc['db_query']('', '
UPDATE {db_prefix}attachments
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $cur_profile['id_member'],
'user' => $subaccount,
)
);
// It's over, no more moderation for you.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}moderators
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}group_moderators
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// If you don't exist we can't ban you.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}ban_items
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Remove individual theme settings.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}themes
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// These users are nobody's buddy nomore.
$request = $smcFunc['db_query']('', '
SELECT id_member, pm_ignore_list, buddy_list
FROM {db_prefix}members
WHERE FIND_IN_SET({int:user}, pm_ignore_list) OR FIND_IN_SET({int:user}, buddy_list)',
array(
'user' => $subaccount,
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
$smcFunc['db_query']('', '
UPDATE {db_prefix}members
SET
pm_ignore_list = {string:pm_ignore_list},
buddy_list = {string:buddy_list}
WHERE id_member = {int:id_member}',
array(
'id_member' => $row['id_member'],
'pm_ignore_list' => implode(',', array_diff(explode(',', $row['pm_ignore_list']), array($subaccount))),
'buddy_list' => implode(',', array_diff(explode(',', $row['buddy_list']), array($subaccount))),
)
);
$smcFunc['db_free_result']($request);
// Make sure no member's birthday is still sticking in the calendar...
updateSettings(array(
'calendar_updated' => time(),
));
updateStats('member');
if (!empty($messageCount))
updateMemberData($cur_profile['id_member'], array('posts' => 'posts + ' . $messageCount));
// Delete the Cache for this user
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
function SubAccountMerge($memID)
{
global $sourcedir, $modSettings, $user_info, $smcFunc, $txt, $context, $cur_profile;
// If we don't even have this request variable, there's nothing we can do here, spit out an error.
if (empty($_REQUEST['subaccount']))
{
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['subaccount_not_selected'];
return SubAccountBrowse($memID);
}
$subaccount = (int) $_REQUEST['subaccount'];
// Let's do some checks first.
// If this is an subaccount, it shouldn't even have subaccounts, but you never know...
// Does the subaccount belong to the user we're trying to remove it from?
if (!empty($cur_profile['id_parent']) || !array_key_exists($subaccount, $cur_profile['subaccounts']))
fatal_lang_error('cannot_delete_subaccount', false);
if (!empty($cur_profile['subaccounts'][$subaccount]['shareable']) && $cur_profile['id_member'] != $cur_profile['subaccounts'][$subaccount]['shareable'])
fatal_lang_error('cannot_delete_subaccount_shared', false);
// Setup the array of subaccounts for the template
$context['subaccounts'] = array();
$context['subaccounts'][$cur_profile['id_member']] = array('id' => $cur_profile['id_member'], 'name' => $cur_profile['real_name']);
$context['subaccounts'] += $cur_profile['subaccounts'];
// Do the actual merge (otherwise display the template to choose who to merge to)
if (!isset($_POST['submit']))
{
$context['sub_template'] = 'manage_subaccounts_merge';
$context['subaccount'] = $subaccount;
$context['page_desc'] = sprintf($txt['subaccounts_merge_desc'], $context['subaccounts'][$subaccount]['name']);
// We don't want to merge a user with itself...
unset($context['subaccounts'][$subaccount]);
return;
}
// Make sure they came from *somewhere*, have a session.
checkSession();
if (empty($_POST['parent']) || (isset($_POST['parent']) && !array_key_exists($_POST['parent'], $context['subaccounts'])))
{
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['subaccount_not_selected'];
return SubAccountBrowse($memID);
}
$parentAccount = (int) $_POST['parent'];
// Get their name for logging purposes.
$request = $smcFunc['db_query']('', '
SELECT id_member, member_name, CASE WHEN id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 THEN 1 ELSE 0 END AS is_admin
FROM {db_prefix}members
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
'admin_group' => 1,
)
);
$row = $smcFunc['db_fetch_assoc']($request);
$smcFunc['db_free_result']($request);
// Make sure they aren't trying to delete administrators if they aren't one. But don't bother checking if it's just themself.
// Just a small check to make sure that the board will never loose their only admin this way
if (!empty($row['is_admin']) && !allowedTo('admin_forum'))
fatal_lang_error('cannot_delete_subaccount', false);
// Log the action - regardless of who is deleting it.
if (!empty($modSettings['modlog_enabled']))
{
$log_inserts = array();
// Add it to both the moderation and admin logs as it effects both.
$log_inserts[] = array(
time(), 3, $user_info['id'], $user_info['ip'], 'merge_subaccount',
0, 0, 0, serialize(array('member' => $row['id_member'], 'name' => $row['member_name'], 'parent' => $context['subaccounts'][$parentAccount])),
);
$log_inserts[] = array(
time(), 1, $user_info['id'], $user_info['ip'], 'merge_subaccount',
0, 0, 0, serialize(array('member' => $row['id_member'], 'name' => $row['member_name'], 'parent' => $context['subaccounts'][$parentAccount])),
);
// Do the actual logging.
$smcFunc['db_insert']('',
'{db_prefix}log_actions',
array(
'log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string',
'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534',
),
$log_inserts,
array('id_action')
);
}
// Integration rocks!
if (isset($modSettings['integrate_delete_member']) && function_exists($modSettings['integrate_delete_member']))
call_user_func($modSettings['integrate_delete_member'], $row['id_member']);
// Remove them from the subaccounts table
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Make these peoples' posts guest posts.
$smcFunc['db_query']('', '
UPDATE {db_prefix}messages
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$messageCount = $smcFunc['db_affected_rows']();
$smcFunc['db_query']('', '
UPDATE {db_prefix}polls
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
// Make these peoples' posts guest first posts and last posts.
$smcFunc['db_query']('', '
UPDATE {db_prefix}topics
SET id_member_started = {int:parent_id}
WHERE id_member_started = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}topics
SET id_member_updated = {int:parent_id}
WHERE id_member_updated = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_actions
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_banned
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_errors
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
// Delete the member.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}members
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Change the logs...
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_actions
SET id_member = {int:parent_id}
WHERE id_log = {int:log_type}
AND id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'log_type' => 2,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_boards
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_group_requests
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_karma
SET id_target = {int:parent_id}
WHERE id_target = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_karma
SET id_executor = {int:parent_id}
WHERE id_executor = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_mark_read
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_notify
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_online
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_topics
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}collapsed_categories
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Make their votes appear as the parents votes - at least it keeps the totals right.
//!!! Consider adding back in cookie protection.
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}log_polls
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
// Still might need some work on this. Not sure that it'll work 100%, but at least
// messages won't be lost (I hope)
$smcFunc['db_query']('', '
UPDATE {db_prefix}pm_recipients
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE {db_prefix}personal_messages
SET id_member_from = {int:parent_id}
WHERE id_member_from = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
// Delete avatar.
require_once($sourcedir . '/ManageAttachments.php');
removeAttachments(array('id_member' => $subaccount));
// Update Attachment Ownership
$smcFunc['db_query']('', '
UPDATE {db_prefix}attachments
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
// It's over, no more moderation for you.
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}moderators
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
$smcFunc['db_query']('', '
UPDATE IGNORE {db_prefix}group_moderators
SET id_member = {int:parent_id}
WHERE id_member = {int:user}',
array(
'parent_id' => $parentAccount,
'user' => $subaccount,
)
);
// If you don't exist we can't ban you.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}ban_items
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Remove individual theme settings.
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}themes
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// These users are nobody's buddy nomore.
$request = $smcFunc['db_query']('', '
SELECT id_member, pm_ignore_list, buddy_list
FROM {db_prefix}members
WHERE FIND_IN_SET({int:user}, pm_ignore_list) OR FIND_IN_SET({int:user}, buddy_list)',
array(
'user' => $subaccount,
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
$smcFunc['db_query']('', '
UPDATE {db_prefix}members
SET
pm_ignore_list = {string:pm_ignore_list},
buddy_list = {string:buddy_list}
WHERE id_member = {int:id_member}',
array(
'id_member' => $row['id_member'],
'pm_ignore_list' => implode(',', array_diff(explode(',', $row['pm_ignore_list']), array($subaccount))),
'buddy_list' => implode(',', array_diff(explode(',', $row['buddy_list']), array($subaccount))),
)
);
$smcFunc['db_free_result']($request);
// Make sure no member's birthday is still sticking in the calendar...
updateSettings(array(
'calendar_updated' => time(),
));
updateStats('member');
if (!empty($messageCount))
updateMemberData($parentAccount, array('posts' => 'posts + ' . $messageCount));
// Delete the Cache for this user
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
function SubAccountSplit($memID)
{
global $context, $smcFunc, $user_info, $txt, $cur_profile, $sourcedir, $user_profile;
// Make sure they came from *somewhere*, have a session.
// If we don't even have this request variable, there's nothing we can do here, spit out an error.
if (empty($_REQUEST['subaccount']))
{
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['subaccount_not_selected'];
return SubAccountBrowse($memID);
}
$subaccount = (int) $_REQUEST['subaccount'];
// Let's do some checks first.
// If this is an subaccount, it shouldn't even have subaccounts, but you never know...
// Does the subaccount belong to the user we're trying to remove it from?
if (!empty($cur_profile['id_parent']) || !array_key_exists($subaccount, $cur_profile['subaccounts']))
fatal_lang_error('cannot_delete_subaccount', false);
if (!empty($cur_profile['subaccounts'][$subaccount]['shareable']) && $cur_profile['id_member'] != $cur_profile['subaccounts'][$subaccount]['shareable'])
fatal_lang_error('cannot_delete_subaccount_shared', false);
if (empty($_POST['submit']))
{
$context['sub_template'] = 'manage_subaccounts_split';
$context['page_desc'] = $txt['subaccounts_split_desc'];
$context['subaccount'] = array(
'id' => $subaccount,
'name' => $cur_profile['subaccounts'][$subaccount]['name'],
);
return;
}
// Do the splits... err... split
// This should be fairly easy... erase the parent ID, reset the password and the email and call
// it a day... Gotta do the proper checks first though. If anyone fails, we fall through on all
// Clean up the POST variables.
$_POST = htmltrim__recursive($_POST);
$_POST = htmlspecialchars__recursive($_POST);
require_once($sourcedir . '/Subs-Auth.php');
$context['post_errors'] = array();
// Check the password
$passwordErrors = validatePassword($_POST['pwmain'], $cur_profile['subaccounts'][$subaccount]);
// Were there errors?
if ($passwordErrors != null)
$context['post_errors'][] = 'password_' . $passwordErrors;
$emailErrors = profileValidateEmail($_POST['email']);
if ($emailErrors !== true)
$context['post_errors'][] = $emailErrors;
if ($_POST['pwmain'] != $_POST['pwverify'])
$context['post_errors'][] = $txt['registration_password_no_match'];
if (!empty($context['post_errors']))
{
loadLanguage('Errors');
$context['custom_error_title'] = $txt['subaccount_error'];
// Reload the info into $context so we can put it back on the form... (just emails, really)
$context['form_email'] = $_POST['email'];
$context['sub_template'] = 'manage_subaccounts_split';
$context['page_desc'] = $txt['subaccounts_split_desc'];
$context['subaccount'] = array(
'id' => $subaccount,
'name' => $cur_profile['subaccounts'][$subaccount]['name'],
);
return;
}
// No errors, woo hooo... update the user...
loadMemberData($subaccount, false, 'minimal');
updateMemberData($subaccount, array('email_address' => $_POST['email'], 'is_shareable' => 0, 'passwd' => sha1(strtolower($user_profile[$subaccount]['member_name']) . un_htmlspecialchars($_POST['pwmain']))));
// Remove them from the subaccounts table
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Delete the Cache for this user
cache_put_data('user_subaccounts-' . $cur_profile['id_member'], null, 240);
redirectexit('action=profile;area=managesubaccounts;u=' . $cur_profile['id_member']);
}
function SubAccountParent($memID)
{
global $context, $txt, $cur_profile, $smcFunc, $sourcedir, $user_profile;
// Here's what we'll do: verify a valid subaccount, update everyone's information, then switch to that subaccount (might change this later, but it makes sense)
if (empty($_REQUEST['subaccount']))
{
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['subaccount_not_selected'];
return SubAccountBrowse($memID);
}
$subaccount = (int) $_REQUEST['subaccount'];
// Let's do some checks first.
// If this is an subaccount, it shouldn't even have subaccounts, but you never know...
if (!empty($cur_profile['id_parent']) || !array_key_exists($subaccount, $cur_profile['subaccounts']))
fatal_lang_error('cannot_delete_subaccount', false);
if (!empty($cur_profile['subaccounts'][$subaccount]['shareable']) && $cur_profile['id_member'] != $cur_profile['subaccounts'][$subaccount]['shareable'])
fatal_lang_error('cannot_delete_subaccount_shared', false);
// Looks like we're good to go, let's do the function...
$passwordError = null;
if (!empty($_POST['submit']))
{
require_once($sourcedir . '/Subs-Auth.php');
$_POST['pwmain'] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST['pwmain']));
$_POST['pwverify'] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST['pwverify']));
$passwordError = validatePassword($_POST['pwmain'], $cur_profile['subaccounts'][$subaccount]);
$passwordError = $passwordError != null ? 'password_' . $passwordError : null;
$passwordError = $_POST['pwmain'] != $_POST['pwverify'] ? 'bad_new_password' : $passwordError;
}
if (empty($_POST['submit']) || $passwordError != null)
{
if ($passwordError != null)
{
loadLanguage('Errors');
$context['custom_error_title'] = $txt['subaccount_error'];
$context['post_errors'][] = $txt['profile_error_' . $passwordError];
}
$context['sub_template'] = 'manage_subaccounts_reassign';
$context['page_desc'] = $txt['subaccounts_reassign_desc'];
$context['subaccount'] = array('id' => $subaccount, 'name' => $cur_profile['subaccounts'][$subaccount]['name']);
return;
}
// Make sure they came from *somewhere*, have a session.
checkSession('post');
// Need to do three different things, first, the new parent can't be a subaccount of anyone
// Remove them from the subaccounts table
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}subaccounts
WHERE id_member = {int:user}',
array(
'user' => $subaccount,
)
);
// Second, we need to convert everyone that has an id_parent of the current user to the new parent
// Remove them from the subaccounts table
$smcFunc['db_query']('', '
UPDATE {db_prefix}subaccounts
SET id_parent = {int:new_parent}
WHERE id_parent = {int:old_parent}',
array(
'new_parent' => $subaccount,
'old_parent' => $cur_profile['id_member'],
)
);
// Lastly, add an entry for the new member into the table
$smcFunc['db_insert']('',
'{db_prefix}subaccounts',
array('id_member' => 'int', 'id_parent' => 'int'),
array($cur_profile['id_member'], $subaccount),
array('id_parent')
);
// Need to get the member data for the new parent for the password creation and set the proper info
loadMemberData($subaccount, false, 'minimal');
updateMemberData($subaccount, array('is_shareable' => 0, 'passwd' => sha1(strtolower($user_profile[$subaccount]['member_name']) . $_POST['pwmain'])));
// And now redirect to the profile of the new parent (the subaccount screen no less)
SwitchSubAccount('action=profile;area=managesubaccounts');
}
function SwitchSubAccount($location = '')
{
global $smcFunc, $user_info, $sourcedir, $modSettings, $cookiename;
// This attempts to set a new cookie with the subaccount id and the password.
// Perhaps incorporating password checking would be good in this... future feature?
// For now we'll rely on current logged in info and a valid session...
checkSession('request');
// Clean the variable, just in case...
$_REQUEST['subaccount'] = !empty($_REQUEST['subaccount']) ? (int) $_REQUEST['subaccount'] : -1;
// If the subaccount doesn't exist in the current users subaccount list, leave, NOW!
if (!array_key_exists($_REQUEST['subaccount'], $user_info['subaccounts']))
redirectexit(empty($location) ? (!empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $_SESSION['old_url']) : $location);
// Get the information for this subaccount
$request = $smcFunc['db_query']('', '
SELECT id_member, passwd, password_salt, is_shareable
FROM {db_prefix}members
WHERE id_member = {int:to_switch}
LIMIT 1',
array(
'to_switch' => $_REQUEST['subaccount'],
)
);
$new_user = $smcFunc['db_fetch_assoc']($request);
$smcFunc['db_free_result']($request);
// Let's setup a new cookie then redirect to wherever we came from
if (isset($_COOKIE[$cookiename]) && preg_match('~^a:[34]:\{i:0;(i:\d{1,6}|s:[1-8]:"\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\d{1,14};(i:3;i:\d;)?\}$~', $_COOKIE[$cookiename]) === 1)
list (, , $timeout) = @unserialize($_COOKIE[$cookiename]);
elseif (isset($_SESSION['login_' . $cookiename]))
list (, , $timeout) = @unserialize($_SESSION['login_' . $cookiename]);
else
trigger_error('SwitchSubAccount(): Cannot change subaccount without a session or cookie', E_USER_ERROR);
// Store the timeout, so the same one is used for possibly too cookies
$timeout -= time();
require_once($sourcedir . '/Subs-Auth.php');
setLoginCookie($timeout, $new_user['id_member'], sha1($new_user['passwd'] . $new_user['password_salt']));
// Create a new cookie so we know where we came from if we are switching to a shareable account
if (!empty($new_user['is_shareable']))
{
// Since this probably won't be happening a lot, a small extra bit of overhead isn't going to kill us here
$id_parent = !empty($user_info['id_parent']) ? $user_info['id_parent'] : $user_info['id'];
$request = $smcFunc['db_query']('', '
SELECT passwd, password_salt
FROM {db_prefix}members
WHERE id_member = {int:id_parent}',
array(
'id_parent' => $id_parent,
)
);
$old_user = $smcFunc['db_fetch_assoc']($request);
setParentCookie($timeout, $id_parent, sha1($old_user['passwd'] . $old_user['password_salt']));
}
// otherwise kill the parent cookie, don't really need it
else
setParentCookie(-3600, 0);
// Update log_online
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_online
SET id_member = {int:new_user}
WHERE id_member = {int:user}',
array(
'new_user' => $new_user['id_member'],
'user' => $user_info['id'],
)
);
// You've logged in, haven't you?
updateMemberData($new_user['id_member'], array('last_login' => time(), 'member_ip' => $user_info['ip'], 'member_ip2' => $_SERVER['BAN_CHECK_IP']));
redirectexit(empty($location) ? (!empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $_SESSION['old_url']) : $location);
}
function setParentCookie($cookie_length, $id, $password = '')
{
global $cookiename, $boardurl, $modSettings;
$subaccount_cookie = $cookiename . '_parent';
// The cookie may already exist, and have been set with different options.
$cookie_state = (empty($modSettings['localCookies']) ? 0 : 1) | (empty($modSettings['globalCookies']) ? 0 : 2);
if (isset($_COOKIE[$subaccount_cookie]) && preg_match('~^a:[34]:\{i:0;(i:\d{1,6}|s:[1-8]:"\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\d{1,14};(i:3;i:\d;)?\}$~', $_COOKIE[$subaccount_cookie]) === 1)
{
$array = @unserialize($_COOKIE[$subaccount_cookie]);
// Out with the old, in with the new!
if (isset($array[3]) && $array[3] != $cookie_state)
{
$cookie_url = url_parts($array[3] & 1 > 0, $array[3] & 2 > 0);
setcookie($subaccount_cookie, serialize(array(0, '', 0)), time() - 3600, $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies']));
}
}
// Get the data and path to set it on.
$data = serialize(empty($id) ? array(0, '', 0) : array($id, $password, time() + $cookie_length, $cookie_state));
$cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies']));
// Set the cookie, $_COOKIE, and session variable.
setcookie($subaccount_cookie, $data, time() + $cookie_length, $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies']));
// If subdomain-independent cookies are on, unset the subdomain-dependent cookie too.
if (empty($id) && !empty($modSettings['globalCookies']))
setcookie($subaccount_cookie, $data, time() + $cookie_length, $cookie_url[1], '', !empty($modSettings['secureCookies']));
// Any alias URLs? This is mainly for use with frames, etc.
if (!empty($modSettings['forum_alias_urls']))
{
$aliases = explode(',', $modSettings['forum_alias_urls']);
$temp = $boardurl;
foreach ($aliases as $alias)
{
// Fake the $boardurl so we can set a different cookie.
$alias = strtr(trim($alias), array('http://' => '', 'https://' => ''));
$boardurl = 'http://' . $alias;
$cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies']));
if ($cookie_url[0] == '')
$cookie_url[0] = strtok($alias, '/');
setcookie($subaccount_cookie, $data, time() + $cookie_length, $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies']));
}
$boardurl = $temp;
}
$_COOKIE[$subaccount_cookie] = $data;
// Make sure the user logs in with a new session ID.
if (!isset($_SESSION['login_' . $subaccount_cookie]) || $_SESSION['login_' . $subaccount_cookie] !== $data)
$_SESSION['login_' . $subaccount_cookie] = $data;
}