2/1/2/patch - Installation Instructions for 2.1.1
SMF 2.1.2

SMF 2.1.2 includes various bug fixes and security updates.

File Edits ALT + Click to collapse all the operations

./cron.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.1
Replace With: Select
* @version 2.1.2
Find: Select
define('SMF_VERSION', '2.1.1');
Replace With: Select
define('SMF_VERSION', '2.1.2');
Find: Select
require_once($sourcedir . '/Subs.php');
Add After: Select


// Ensure we don't trip over disabled internal functions
if (version_compare(PHP_VERSION, '8.0.0', '>='))
require_once($sourcedir . '/Subs-Compat.php');

./index.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.1
Replace With: Select
* @version 2.1.2
Find: Select
define('SMF_VERSION', '2.1.1');
Replace With: Select
define('SMF_VERSION', '2.1.2');
Find: Select
'taskddir'
Replace With: Select
'tasksdir'
Find: Select
require_once($sourcedir . '/Security.php');
Add After: Select


// Ensure we don't trip over disabled internal functions
if (version_compare(PHP_VERSION, '8.0.0', '>='))
require_once($sourcedir . '/Subs-Compat.php');

./proxy.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.1
Replace With: Select
* @version 2.1.2
Find: Select
define('SMF_VERSION', '2.1.1');
Replace With: Select
define('SMF_VERSION', '2.1.2');
Find: Select
require_once($sourcedir . '/Subs.php');
Add After: Select


// Ensure we don't trip over disabled internal functions
if (version_compare(PHP_VERSION, '8.0.0', '>='))
require_once($sourcedir . '/Subs-Compat.php');

./SSI.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.1
Replace With: Select
* @version 2.1.2
Find: Select
define('SMF_VERSION', '2.1.1');
Replace With: Select
define('SMF_VERSION', '2.1.2');
Find: Select
global $boardurl, $boarddir, $sourcedir, $webmaster_email, $cookiename
Add After: Select
, $db_character_set
Find: Select
require_once($sourcedir . '/Subs-Auth.php');
Add After: Select


// Ensure we don't trip over disabled internal functions
if (version_compare(PHP_VERSION, '8.0.0', '>='))
require_once($sourcedir . '/Subs-Compat.php');

./subscriptions.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
require_once($sourcedir . '/Subs-Admin.php');
Add After: Select


// Ensure we don't trip over disabled internal functions
if (version_compare(PHP_VERSION, '8.0.0', '>='))
require_once($sourcedir . '/Subs-Compat.php');

./Sources/Attachments.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$attachmentOptions['errors'][] = vsprintf($txt['attach_warning'], $attachment['name']);
Replace With: Select
$attachmentOptions['errors'][] = sprintf($txt['attach_warning'], $attachment['name']);
Find: Select
$attachmentOptions['errors'][] = vsprintf($txt[$error[0]], $error[1]);
Replace With: Select
$attachmentOptions['errors'][] = vsprintf($txt[$error[0]], (array) $error[1]);
Find: Select
$this->_generalErrors[$k] = (is_array($v) ? vsprintf($txt[$v[0]], $v[1]) : $txt[$v]);
Replace With: Select
$this->_generalErrors[$k] = (is_array($v) ? vsprintf($txt[$v[0]], (array) $v[1]) : $txt[$v]);

./Sources/Cache/APIs/FileBased.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$context['settings_post_javascript'] .= '
Add Before: Select
if (empty($context['settings_not_writable']))

./Sources/Cache/APIs/MemcacheImplementation.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$context['settings_post_javascript'] .= '
Add Before: Select
if (empty($context['settings_not_writable']))

./Sources/Cache/APIs/MemcachedImplementation.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$context['settings_post_javascript'] .= '
Add Before: Select
if (empty($context['settings_not_writable']))

./Sources/Cache/APIs/Sqlite.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$context['settings_post_javascript'] .= '
Add Before: Select
if (empty($context['settings_not_writable']))

./Sources/Calendar.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$start_parsed = date_parse(convertDateToEnglish($_REQUEST['start_date']));
Replace With: Select
$start_parsed = date_parse(str_replace(',', '', convertDateToEnglish($_REQUEST['start_date'])));
Find: Select
$start_object = checkdate($month, $day, $year) === true ? date_create(implode('-', array($year, $month, $day))) : date_create(implode('-', array($today['year'], $today['month'], $today['day'])));
Replace With: Select
$start_object = checkdate($month, $day, $year) === true ? date_create(implode('-', array($year, $month, $day)) . ' ' . getUserTimezone()) : date_create(implode('-', array($today['year'], $today['month'], $today['day'])) . ' ' . getUserTimezone());
Find: Select
$end_parsed = date_parse(convertDateToEnglish($_REQUEST['end_date']));
Replace With: Select
$end_parsed = date_parse(str_replace(',', '', convertDateToEnglish($_REQUEST['end_date'])));
Find: Select
$end_object = date_create(implode('-', array($end_year, $end_month, $end_day)));
Replace With: Select
$end_object = date_create(implode('-', array($end_year, $end_month, $end_day)) . ' ' . getUserTimezone());
Find: Select
$end_object = date_create(date_format($start_object, 'Y-m-d'));
Replace With: Select
$end_object = date_create(date_format($start_object, 'Y-m-d') . ' ' . getUserTimezone());

./Sources/Errors.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
// Send the status header - set this to 0 or false if you don't want to send one at all
Add Before: Select
// Ensure this is an array.
$sprintf = (array) $sprintf;

./Sources/Groups.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
<select name="req_action" onchange="if (this.value != 0 &amp;&amp; (this.value == \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();">
Replace With: Select
<select id="req_action" name="req_action" onchange="if (this.value != 0 &amp;&amp; (this.value == \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();">

./Sources/Load.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.1
Replace With: Select
* @version 2.1.2
Find: Select
if (!empty($db_character_set))
$smcFunc['db_query']('', '
SET NAMES {string:db_character_set}',
array(
'db_character_set' => $db_character_set,
)
);
Replace With: Select
if (empty($db_character_set))
$db_character_set = 'utf8';
$smcFunc['db_query']('', '
SET NAMES {string:db_character_set}',
array(
'db_character_set' => $db_character_set,
)
);
Find: Select
// Enclosing the user input within some other text?
Add After: Select

$simple_value = $value;
Find: Select
'value' => un_htmlspecialchars(tokenTxtReplace($value)),
Add After: Select

'simple' => tokenTxtReplace($simple_value),
Find: Select
if ((!empty($options['show_no_censored']) && !empty($modSettings['allow_no_censored']) && !$force) || empty($modSettings['censor_vulgar']) || trim($text) === '')
Replace With: Select
if ((!empty($options['show_no_censored']) && !empty($modSettings['allow_no_censored']) && !$force) || empty($modSettings['censor_vulgar']) || !is_string($text) || trim($text) === '')
Find: Select
// If they haven't yet been loaded, load them.
Add Before: Select
call_integration_hook('integrate_word_censor', array(&$text));

./Sources/ManagePermissions.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
'post_unapproved_replies' => array(true, 'topic'),
'post_reply' => array(true, 'topic'),
Replace With: Select
'post_reply' => array(true, 'topic'),
'post_unapproved_replies' => array(true, 'topic'),

./Sources/ManageSearchEngines.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$date_select = '
Add Before: Select
if (!empty($date_choices))
{
Find: Select
if (empty($date_choices))
$date_select .= '
<option></option>';
else
foreach ($date_choices as $id => $text)
Replace With: Select
foreach ($date_choices as $id => $text)
Find: Select
$date_select .= '
</select>
Replace With: Select
$date_select .= '
</select>
Find: Select
</noscript>';
Add After: Select

}
Find: Select
'title' => $txt['spider'] . ' ' . $txt['spider_stats'],
Replace With: Select
'title' => $txt['spider_stats'],
Find: Select
'additional_rows' => array(
array(
'position' => 'below_table_data',
Replace With: Select
'additional_rows' => empty($date_select) ? array() : array(
array(
'position' => 'below_table_data',

./Sources/ManageServer.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
if ($settings_not_writable)
$context['settings_message'] = array(
'label' => $txt['settings_not_writable'],
'tag' => 'div',
'class' => 'centertext strong'
);
elseif ($settings_backup_fail)
Replace With: Select
if ($settings_backup_fail)
Find: Select
// If no cert, force_ssl must remain 0
require_once($sourcedir . '/Subs.php');
if (!ssl_cert_found($boardurl) && empty($modSettings['force_ssl']))
$disable_force_ssl = true;
else
$disable_force_ssl = false;

/* If you're writing a mod, it's a bad idea to add things here....
For each option:
Replace With: Select
/* If you're writing a mod, it's a bad idea to add things here....
For each option:
Find: Select
array('force_ssl', $txt['force_ssl'], 'db', 'select', array($txt['force_ssl_off'], $txt['force_ssl_complete']), 'force_ssl', 'disabled' => $disable_force_ssl),
Replace With: Select
'force_ssl' => array('force_ssl', $txt['force_ssl'], 'db', 'select', array($txt['force_ssl_off'], $txt['force_ssl_complete']), 'force_ssl'),
Find: Select
// Setup the template stuff.
$context['post_url'] = $scripturl . '?action=admin;area=serversettings;sa=general;save';
Add Before: Select
// If no cert, force_ssl must remain 0 (The admin search doesn't require this)
$config_vars['force_ssl']['disabled'] = empty($modSettings['force_ssl']) && !ssl_cert_found($boardurl);

Find: Select
$context['settings_title'] = $txt['general_settings'];
Add After: Select

$context['save_disabled'] = $context['settings_not_writable'];
Find: Select
// Some javascript for SSL
addInlineJavaScript('
Replace With: Select
// Some javascript for SSL
if (empty($context['settings_not_writable']))
addInlineJavaScript('
Find: Select
$context['settings_title'] = $txt['cookies_sessions_settings'];
Replace With: Select
$context['settings_title'] = $txt['cookies_sessions_settings'];
$context['save_disabled'] = $context['settings_not_writable'];
Find: Select
global $context, $scripturl, $txt, $cacheAPI, $cache_enable
Add After: Select
, $cache_accelerator
Find: Select
global $context, $modSettings, $smcFunc;
Replace With: Select
global $context, $modSettings, $smcFunc, $txt;

if (!empty($context['settings_not_writable']))
$context['settings_message'] = array(
'label' => $txt['settings_not_writable'],
'tag' => 'div',
'class' => 'centertext strong'
);

./Sources/ManageSettings.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
'answers' => $smcFunc['json_decode']($row['answers'], true),
Replace With: Select
'answers' => (array) $smcFunc['json_decode']($row['answers'], true),

./Sources/Memberlist.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
'down' => 'mem.website_url = \'\', mem.website_url is null, mem.website_url DESC',
'up' => 'mem.website_url != \'\', mem.website_url is not null, mem.website_url ASC'
Replace With: Select
'down' => $context['user']['is_guest'] ? '1=1' : 'mem.website_url = \'\', mem.website_url is null, mem.website_url DESC',
'up' => $context['user']['is_guest'] ? ' 1=1' : 'mem.website_url != \'\', mem.website_url is not null, mem.website_url ASC'
Find: Select
// Are we sorting the results
Add Before: Select
// Don't offer website sort to guests
if ($context['user']['is_guest'])
{
$context['columns']['website_url']['href'] = '';
$context['columns']['website_url']['link'] = $context['columns']['website_url']['label'];
}

Find: Select
$context['search_fields']['cust_' . $field['colname']] = sprintf($txt['mlist_search_by'], $field['name']);
Replace With: Select
$context['search_fields']['cust_' . $field['colname']] = sprintf($txt['mlist_search_by'], tokenTxtReplace($field['name']));

./Sources/MessageIndex.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$moveCache[0][] = $topic;
Add Before: Select
// Never move topics to redirect boards
$redirect_boards = array();
$request = $smcFunc['db_query']('', '
SELECT id_board
FROM {db_prefix}boards
WHERE redirect != {string:blank_redirect}',
array(
'blank_redirect' => '',
)
);
while ($row = $smcFunc['db_fetch_row']($request))
$redirect_boards[] = $row[0];
$smcFunc['db_free_result']($request);

if (in_array($moveCache[1][$topic], $redirect_boards))
continue;

./Sources/News.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
'content' => $custom_field['raw'],
Replace With: Select
'content' => $custom_field['simple'],

./Sources/Post.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$txt['error_attach_initial_error'] = $txt['attach_no_upload'] . '<div style="padding: 0 1em;">' . (is_array($attachment) ? vsprintf($txt[$attachment[0]], $attachment[1]) : $txt[$attachment]) . '</div>';
Replace With: Select
$txt['error_attach_initial_error'] = $txt['attach_no_upload'] . '<div style="padding: 0 1em;">' . (is_array($attachment) ? vsprintf($txt[$attachment[0]], (array) $attachment[1]) : $txt[$attachment]) . '</div>';
Find: Select
$txt['error_attach_errors'] .= vsprintf($txt['attach_warning'], $attachment['name']) . '<div style="padding: 0 1em;">';
Replace With: Select
$txt['error_attach_errors'] .= sprintf($txt['attach_warning'], $attachment['name']) . '<div style="padding: 0 1em;">';
Find: Select
$txt['error_attach_errors'] .= (is_array($error) ? vsprintf($txt[$error[0]], $error[1]) : $txt[$error]) . '<br >';
Replace With: Select
$txt['error_attach_errors'] .= (is_array($error) ? vsprintf($txt[$error[0]], (array) $error[1]) : $txt[$error]) . '<br >';
Find: Select
$context['post_error'][$post_error_id] = vsprintf($txt['error_' . $post_error_id], $post_error[1]);
Replace With: Select
$context['post_error'][$post_error_id] = vsprintf($txt['error_' . $post_error_id], (array) $post_error[1]);
Find: Select
// Show the max number of attachments if not 0.
if ($type == 'attachmentNumPerPostLimit')
$context['attachment_restrictions'][] = sprintf($txt['attach_remaining'], max($modSettings['attachmentNumPerPostLimit'] - $context['attachments']['quantity'], 0));
Replace With: Select
$context['attachment_restrictions'][$type] = sprintf($txt['attach_restrict_' . $type . ($modSettings[$type] >= 1024 ? '_MB' : '')], comma_format($modSettings[$type] >= 1024 ? $modSettings[$type] / 1024 : $modSettings[$type], 2));

// Show the max number of attachments if not 0.
if ($type == 'attachmentNumPerPostLimit')
{
$context['attachment_restrictions'][$type] .= ' (' . sprintf($txt['attach_remaining'], max($modSettings['attachmentNumPerPostLimit'] - $context['attachments']['quantity'], 0)) . ')';
}
elseif ($type == 'attachmentPostLimit' && $context['attachments']['total_size'] > 0)
{
$context['attachment_restrictions'][$type] .= '<span class="attach_available"> (' . sprintf($txt['attach_available'], max($modSettings['attachmentPostLimit'] - ($context['attachments']['total_size'] / 1024), 0)) . ')</span>';
}

Find: Select
$attach_errors[] = '<dd>' . (is_array($attachment) ? vsprintf($txt[$attachment[0]], $attachment[1]) : $txt[$attachment]) . '</dd>';
Replace With: Select
$attach_errors[] = '<dd>' . (is_array($attachment) ? vsprintf($txt[$attachment[0]], (array) $attachment[1]) : $txt[$attachment]) . '</dd>';
Find: Select
$attach_errors[] = '<dt>' . vsprintf($txt['attach_warning'], $attachment['name']) . '</dt>';
Replace With: Select
$attach_errors[] = '<dt>' . sprintf($txt['attach_warning'], $attachment['name']) . '</dt>';
Find: Select
$attach_errors[] = '<dd>' . vsprintf($txt[$error[0]], $error[1]) . '</dd>';
Replace With: Select
$attach_errors[] = '<dd>' . vsprintf($txt[$error[0]], (array) $error[1]) . '</dd>';
Find: Select
}
unset($_SESSION['temp_attachments']);
}
Replace With: Select
}
}
unset($_SESSION['temp_attachments']);

./Sources/Profile-Export.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
// We should now have what we need to serve the file.
Add Before: Select
// Allow access to their attachments even if they can't see the board.
// This is just like what we do with posts during export.
$context['attachment_allow_hidden_boards'] = true;

Find: Select
if (strtotime($modified_since) >= $mtime)
{
ob_end_clean();
Replace With: Select
if (strtotime($modified_since) >= $mtime)
{
ob_end_clean();
header_remove('content-encoding');
Find: Select
if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false)
{
ob_end_clean();
Replace With: Select
if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false)
{
ob_end_clean();
header_remove('content-encoding');
Find: Select
// 40 kilobytes is a good-ish amount
Replace With: Select
header_remove('content-encoding');

// 40 kilobytes is a good-ish amount
Find: Select
$fp = fopen($filepath, 'rb');
while (!feof($fp))
Replace With: Select
header_remove('content-encoding');

$fp = fopen($filepath, 'rb');
while (!feof($fp))
Find: Select

// We need the topic.
list ($_REQUEST['topic']) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);

// This doesn't count as a normal download.
Replace With: Select
$smcFunc['db_free_result']($request);

// This doesn't count as a normal download.

./Sources/Profile-Modify.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
if (isset($_POST['sa']) && $_POST['sa'] == 'ignoreboards' && empty($_POST['ignore_brd']))
$_POST['ignore_brd'] = array();
Replace With: Select
if (isset($_POST['sa']) && $_POST['sa'] == 'ignoreboards' && empty($_POST['brd']))
$_POST['brd'] = array();
Find: Select
if (isset($_POST['ignore_brd']))
Replace With: Select
if (isset($_POST['brd']))
Find: Select
if (!is_array($_POST['ignore_brd']))
$_POST['ignore_brd'] = array($_POST['ignore_brd']);
Replace With: Select
if (!is_array($_POST['brd']))
$_POST['brd'] = array($_POST['brd']);
Find: Select
foreach ($_POST['ignore_brd'] as $k => $d)
Replace With: Select
foreach ($_POST['brd'] as $k => $d)
Find: Select
$_POST['ignore_brd'][$k] = $d;
Replace With: Select
$_POST['brd'][$k] = $d;
Find: Select
unset($_POST['ignore_brd'][$k]);
Replace With: Select
unset($_POST['brd'][$k]);
Find: Select
$_POST['ignore_boards'] = implode(',', $_POST['ignore_brd']);
unset($_POST['ignore_brd']);
Replace With: Select
$_POST['ignore_boards'] = implode(',', $_POST['brd']);
unset($_POST['brd']);
Find: Select
if ($row['mask'] == 'nohtml' && ($valueReference != strip_tags($valueReference) || $value != filter_var($value, FILTER_SANITIZE_STRING) || preg_match('/<(.+?)[\s]*\/?[\s]*>/si', $valueReference)))
Replace With: Select
if ($row['mask'] == 'nohtml' && ($valueReference != strip_tags($valueReference) || $value != filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS) || preg_match('/<(.+?)[\s]*\/?[\s]*>/si', $valueReference)))
Find: Select
SELECT col_name, field_name, field_desc, field_type, bbc, enclose
Replace With: Select
SELECT col_name, field_name, field_desc, field_type, field_options, show_mlist, bbc, enclose
Find: Select
if (!isset($disabled_fields[$row['col_name']]))
Replace With: Select
if (!isset($disabled_fields[$row['col_name']]) && !empty($row['show_mlist']))
Find: Select
'label' => $row['field_name'],
Replace With: Select
'label' => tokenTxtReplace($row['field_name']),
Find: Select
'type' => $row['field_type'],
Add After: Select

'options' => !empty($row['field_options']) ? explode(',', $row['field_options']) : array(),
Find: Select
// Gotta disable the gender option.
if (isset($context['custom_pf']['cust_gender']) && $context['custom_pf']['cust_gender'] == 'None')
unset($context['custom_pf']['cust_gender']);

$smcFunc['db_free_result']($request);

if (!empty($buddiesArray))
Replace With: Select
$smcFunc['db_free_result']($request);

if (!empty($buddiesArray))
Find: Select
if ($column['bbc'] && !empty($context['buddies'][$buddy]['options'][$key]))
Add Before: Select
$currentKey = 0;
if (!empty($column['options']))
{
foreach ($column['options'] as $k => $v)
{
if (empty($currentKey))
$currentKey = $v == $context['buddies'][$buddy]['options'][$key] ? $k : 0;
}
}

Find: Select
'{INPUT}' => $context['buddies'][$buddy]['options'][$key],
Replace With: Select
'{KEY}' => $currentKey,
'{INPUT}' => tokenTxtReplace($context['buddies'][$buddy]['options'][$key]),
Find: Select
$context['member']['signature'] = empty($cur_profile['signature']) ? '' : str_replace(array('<br>', '<', '>', '"', '\''), array("\n", '&lt;', '&gt;', '&quot;', '&#039;'), $cur_profile['signature']);
Replace With: Select
$context['member']['signature'] = empty($cur_profile['signature']) ? '' : str_replace(array('<br>', '<br/>', '<br />', '<', '>', '"', '\''), array("\n", "\n", "\n", '&lt;', '&gt;', '&quot;', '&#039;'), $cur_profile['signature']);

./Sources/Register.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$reg_errors[] = vsprintf($txt['error_' . $error[0]], $error[1]);
Replace With: Select
$reg_errors[] = vsprintf($txt['error_' . $error[0]], (array) $error[1]);

./Sources/Search.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$weight_factors = array(
Add Before: Select
if (isset($_REQUEST['start']))
$_REQUEST['start'] = (int) $_REQUEST['start'];

Find: Select
$counter = $_REQUEST['start'] + 1;
Replace With: Select
$counter = ((int) $_REQUEST['start']) + 1;

./Sources/ShowAttachments.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
// This is done to clear any output that was made before now.
ob_end_clean();
Replace With: Select
// This is done to clear any output that was made before now.
ob_end_clean();
header_remove('content-encoding');
Find: Select
// A thumbnail has been requested? madness! madness I say!
$preview = isset($_REQUEST['preview']) ? $_REQUEST['preview'] : (isset($_REQUEST['type']) && $_REQUEST['type'] == 'preview' ? $_REQUEST['type'] : 0);
$showThumb = isset($_REQUEST['thumb']);
$attachTopic = isset($_REQUEST['topic']) ? (int) $_REQUEST['topic'] : 0;
Replace With: Select
// A thumbnail has been requested? madness! madness I say!
$showThumb = isset($_REQUEST['thumb']);
Find: Select
// No access in strict maintenance mode or you don't have permission to see attachments.
if ((!empty($maintenance) && $maintenance == 2) || (!allowedTo('view_attachments') && !isset($_SESSION['attachments_can_preview'][$attachId])))
Replace With: Select
// No access in strict maintenance mode.
if (!empty($maintenance) && $maintenance == 2)
Find: Select
id_folder, filename, file_hash, fileext, id_attach,
id_thumb, attachment_type, mime_type, approved, id_msg
FROM {db_prefix}attachments
WHERE id_attach = {int:attach}' . (!empty($context['preview_message']) ? '
AND a.id_msg != 0' : '') . '
Replace With: Select
{string:source} AS source,
a.id_folder, a.filename, a.file_hash, a.fileext, a.id_attach,
a.id_thumb, a.attachment_type, a.mime_type, a.approved, a.id_msg,
m.id_board
FROM {db_prefix}attachments AS a
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
WHERE a.id_attach = {int:attach}
Find: Select
'attach' => $attachId,
)
Add Before: Select
'source' => 'SMF',
Find: Select
// If theres a message ID stored, we NEED a topic ID.
if (!empty($file['id_msg']) && empty($attachTopic) && empty($preview))
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}

// Previews doesn't have this info.
if (empty($preview) && is_resource($attachRequest))
{
$request2 = $smcFunc['db_query']('', '
SELECT a.id_msg
FROM {db_prefix}attachments AS a
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
WHERE {query_see_message_board}
AND a.id_attach = {int:attach}
LIMIT 1',
array(
'attach' => $attachId,
'current_topic' => $attachTopic,
)
);

// The provided topic must match the one stored in the DB for this particular attachment, also.
if ($smcFunc['db_num_rows']($request2) == 0)
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}

$smcFunc['db_free_result']($request2);
}

// If attachment is unapproved, see if user is allowed to approve
if (!$file['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts'))
{
$request3 = $smcFunc['db_query']('', '
SELECT id_member
FROM {db_prefix}messages
WHERE id_msg = {int:id_msg}
LIMIT 1',
array(
'id_msg' => $file['id_msg'],
)
);

$id_member = $smcFunc['db_fetch_assoc']($request3)['id_member'];
$smcFunc['db_free_result']($request3);

// Let users see own unapproved attachments
if ($id_member != $user_info['id'])
{
send_http_status(403, 'Forbidden');
die('403 Forbidden');
}
}

// set filePath and ETag time
$file['filePath'] = getAttachmentFilename($file['filename'], $attachId, $file['id_folder'], false, $file['file_hash']);
Replace With: Select
// set filePath and ETag time
$file['filePath'] = getAttachmentFilename($file['filename'], $attachId, $file['id_folder'], false, $file['file_hash']);
Find: Select
$file['filePath'] = !file_exists($file['filePath']) && isset($filePath['extension']) ? substr($file['filePath'], 0, -(strlen($filePath['extension']) + 1)) : $file['filePath'];
$file['etag'] = '"' . md5_file($file['filePath']) . '"';
Replace With: Select
$file['exists'] = file_exists($file['filePath']);
$file['filePath'] = !$file['exists'] && isset($filePath['extension']) ? substr($file['filePath'], 0, -(strlen($filePath['extension']) + 1)) : $file['filePath'];
$file['mtime'] = $file['exists'] ? filemtime($file['filePath']) : 0;
$file['size'] = $file['exists'] ? filesize($file['filePath']) : 0;
$file['etag'] = '"' . sha1_file($file['filePath']) . '"';
Find: Select
// set filePath and ETag time
$thumbFile['filePath'] = getAttachmentFilename($thumbFile['filename'], $thumbFile['id_attach'], $thumbFile['id_folder'], false, $thumbFile['file_hash']);
$thumbFile['etag'] = '"' . md5_file($thumbFile['filePath']) . '"';
Replace With: Select
$thumbFile['filePath'] = getAttachmentFilename($thumbFile['filename'], $thumbFile['id_attach'], $thumbFile['id_folder'], false, $thumbFile['file_hash']);
$thumbPath = pathinfo($thumbFile['filePath']);

// set filePath and ETag time
$thumbFile['exists'] = file_exists($thumbFile['filePath']);
$thumbFile['filePath'] = !$thumbFile['exists'] && isset($thumbPath['extension']) ? substr($thumbFile['filePath'], 0, -(strlen($thumbPath['extension']) + 1)) : $thumbFile['filePath'];
$thumbFile['mtime'] = $thumbFile['exists'] ? filemtime($thumbFile['filePath']) : 0;
$thumbFile['size'] = $thumbFile['exists'] ? filesize($thumbFile['filePath']) : 0;
$thumbFile['etag'] = '"' . sha1_file($thumbFile['filePath']) . '"';
Find: Select
// Replace the normal file with its thumbnail if it has one!
Add Before: Select
// Can they see attachments on this board?
if (!empty($file['id_msg']))
{
// Special case for profile exports.
if (!empty($context['attachment_allow_hidden_boards']))
{
$boards_allowed = array(0);
}
// Check permissions and board access.
elseif (($boards_allowed = cache_get_data('view_attachment_boards_id-' . $user_info['id'])) == null)
{
$boards_allowed = boardsAllowedTo('view_attachments');
cache_put_data('view_attachment_boards_id-' . $user_info['id'], $boards_allowed, mt_rand(850, 900));
}
}

// No access if you don't have permission to see this attachment.
if
(
// This was from SMF or a hook didn't claim it.
(
empty($file['source'])
|| $file['source'] == 'SMF'
)
&& (
// No id_msg and no id_member, so we don't know where its from.
// Avatars will have id_msg = 0 and id_member > 0.
(
empty($file['id_msg'])
&& empty($file['id_member'])
)
// When we have a message, we need a board and that board needs to
// let us view the attachment.
|| (
!empty($file['id_msg'])
&& (
empty($file['id_board'])
|| ($boards_allowed !== array(0) && !in_array($file['id_board'], $boards_allowed))
)
)
)
// We are not previewing an attachment.
&& !isset($_SESSION['attachments_can_preview'][$attachId])
)
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}

// If attachment is unapproved, see if user is allowed to approve
if (!$file['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts'))
{
$request = $smcFunc['db_query']('', '
SELECT id_member
FROM {db_prefix}messages
WHERE id_msg = {int:id_msg}
LIMIT 1',
array(
'id_msg' => $file['id_msg'],
)
);

$id_member = $smcFunc['db_fetch_assoc']($request)['id_member'];
$smcFunc['db_free_result']($request);

// Let users see own unapproved attachments
if ($id_member != $user_info['id'])
{
send_http_status(403, 'Forbidden');
die('403 Forbidden');
}
}

Find: Select
if (!file_exists($file['filePath']))
Replace With: Select
if (empty($file['exists']))
Find: Select
if (strtotime($modified_since) >= filemtime($file['filePath']))
{
ob_end_clean();
Replace With: Select
if (!empty($file['mtime']) && strtotime($modified_since) >= $file['mtime'])
{
ob_end_clean();
header_remove('content-encoding');
Find: Select
$eTag = '"' . substr($_REQUEST['attach'] . $file['filePath'] . filemtime($file['filePath']), 0, 64) . '"';
if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false)
{
ob_end_clean();
Replace With: Select
if (!empty($file['etag']) && !empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $file['etag']) !== false)
{
ob_end_clean();
header_remove('content-encoding');
Find: Select
$range = 0;
$size = filesize($file['filePath']);
Replace With: Select
$range = 0;
Find: Select
$range_end = !$range_end ? $size - 1 : intval($range_end);
Replace With: Select
$range_end = !$range_end ? $file['size'] - 1 : intval($range_end);
Find: Select
header('last-modified: ' . gmdate('D, d M Y H:i:s', filemtime($file['filePath'])) . ' GMT');
Replace With: Select
header('last-modified: ' . gmdate('D, d M Y H:i:s', $file['mtime']) . ' GMT');
Find: Select
header('etag: ' . $eTag);
Replace With: Select
header('etag: ' . $file['etag']);
Find: Select
header("content-range: bytes $range-$range_end/$size");
Replace With: Select
header("content-range: bytes $range-$range_end/$file[size]");
Find: Select
header("content-length: " . $size);
Replace With: Select
header("content-length: " . $file['size']);

// Allow customizations to hook in here before we send anything to modify any headers needed. Or to change the process of how we output.
call_integration_hook('integrate_download_headers');
Find: Select
// 40 kilobytes is a good-ish amount
Add Before: Select
header_remove('content-encoding');

Find: Select
elseif ($size > 4194304)
Replace With: Select
elseif ($file['size'] > 4194304)
Find: Select
$fp = fopen($file['filePath'], 'rb');
while (!feof($fp))
Add Before: Select
header_remove('content-encoding');

./Sources/Subs-Admin.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
if (!empty($setting_def['text']) && strpos($substitutions[$var]['replacement'], $setting_def['text']) === false)
Replace With: Select
if (is_string($var) && !empty($setting_def['text']) && strpos($substitutions[$var]['replacement'], $setting_def['text']) === false)

./Sources/Subs-Attachments.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
if (empty($attachInfo) || empty($attachInfo['msg']) && empty($context['preview_message']))
Replace With: Select
if (empty($attachInfo))
return 'attachments_no_data_loaded';

if (empty($attachInfo['msg']) && empty($context['preview_message']))
Find: Select
// Previewing much? No msg ID has been set yet.
if (!empty($context['preview_message']))
{
$attachContext['href'] = $scripturl . '?action=dlattach;attach=' . $attachID . ';type=preview';

$attachContext['link'] = '<a href="' . $scripturl . '?action=dlattach;attach=' . $attachID . ';type=preview' . (empty($attachContext['is_image']) ? ';file' : '') . '" class="bbc_link">' . $smcFunc['htmlspecialchars']($attachContext['name']) . '</a>';

// Fix the thumbnail too, if the image has one.
if (!empty($attachContext['thumbnail']) && !empty($attachContext['thumbnail']['has_thumb']))
$attachContext['thumbnail']['href'] = $scripturl . '?action=dlattach;attach=' . $attachContext['thumbnail']['id'] . ';image;type=preview';
}

// You may or may not want to show this under the post.
Replace With: Select
// You may or may not want to show this under the post.
Find: Select
'href' => $scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach'],
Replace With: Select
'href' => $scripturl . '?action=dlattach;attach=' . $attachment['id_attach'],
Find: Select
'link' => '<a href="' . $scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach'] . '" class="bbc_link">' . $smcFunc['htmlspecialchars']($attachment['filename']) . '</a>',
Replace With: Select
'link' => '<a href="' . $scripturl . '?action=dlattach;attach=' . $attachment['id_attach'] . '" class="bbc_link">' . $smcFunc['htmlspecialchars']($attachment['filename']) . '</a>',
Find: Select
'href' => $scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_thumb'] . ';image',
Replace With: Select
'href' => $scripturl . '?action=dlattach;attach=' . $attachment['id_thumb'] . ';image',

./Sources/Subs-Auth.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3])) : $error[1];
Replace With: Select
$message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], (array) $error[3])) : $error[1];

./Sources/Subs-Calendar.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$timezone_array['default'] = timezone_open(date_default_timezone_get());
Replace With: Select
$timezone_array['default'] = timezone_open(getUserTimezone());
Find: Select
$low_object = date_create($low_date);
Replace With: Select
$low_object = date_create($low_date, $timezone_array['default']);
Find: Select
$high_object = date_create($high_date);
Replace With: Select
$high_object = date_create($high_date, $timezone_array['default']);
Find: Select
'day' => (int) smf_strftime('%d', time()),
Replace With: Select
'day' => (int) smf_strftime('%d', time(), getUserTimezone()),
Find: Select
'month' => (int) smf_strftime('%m', time()),
Replace With: Select
'month' => (int) smf_strftime('%m', time(), getUserTimezone()),
Find: Select
'year' => (int) smf_strftime('%Y', time()),
Replace With: Select
'year' => (int) smf_strftime('%Y', time(), getUserTimezone()),
Find: Select
'date' => smf_strftime('%Y-%m-%d', time()),
Replace With: Select
'date' => smf_strftime('%Y-%m-%d', time(), getUserTimezone()),
Find: Select
global $scripturl, $modSettings;

$selected_object = date_create($selected_date);
Replace With: Select
global $scripturl, $modSettings;

$selected_object = date_create($selected_date . ' ' . getUserTimezone());
Find: Select
$next_object = date_create($selected_date);
$next_object->modify('first day of next month');
Replace With: Select
$next_object = date_create($selected_date . ' ' . getUserTimezone());
$next_object->modify('first day of next month');
Find: Select
$prev_object = date_create($selected_date);
$prev_object->modify('first day of previous month');
Replace With: Select
$prev_object = date_create($selected_date . ' ' . getUserTimezone());
$prev_object->modify('first day of previous month');
Find: Select
$first_day_object = date_create(date_format($selected_object, 'Y-m-01'));
$last_day_object = date_create(date_format($selected_object, 'Y-m-t'));
Replace With: Select
$first_day_object = date_create(date_format($selected_object, 'Y-m-01') . ' ' . getUserTimezone());
$last_day_object = date_create(date_format($selected_object, 'Y-m-t') . ' ' . getUserTimezone());
Find: Select
'first_day_of_year' => date_format(date_create(date_format($selected_object, 'Y-01-01')), 'w'),
'first_day_of_next_year' => date_format(date_create((date_format($selected_object, 'Y') + 1) . '-01-01'), 'w'),
Replace With: Select
'first_day_of_year' => date_format(date_create(date_format($selected_object, 'Y-01-01') . ' ' . getUserTimezone()), 'w'),
'first_day_of_next_year' => date_format(date_create((date_format($selected_object, 'Y') + 1) . '-01-01' . ' ' . getUserTimezone()), 'w'),
Find: Select
$selected_object = date_create($selected_date);

// Get today's date.
Replace With: Select
$selected_object = date_create($selected_date . ' ' . getUserTimezone());

// Get today's date.
Find: Select
$first_day_object = date_create($selected_date);
Replace With: Select
$first_day_object = date_create($selected_date . ' ' . getUserTimezone());
Find: Select
$last_day_object = date_create(date_format($first_day_object, 'Y-m-d'));
Replace With: Select
$last_day_object = date_create(date_format($first_day_object, 'Y-m-d') . ' ' . getUserTimezone());
Find: Select
$next_object = date_create($selected_date);
date_add($next_object, date_interval_create_from_date_string('1 week'));
Replace With: Select
$next_object = date_create($selected_date . ' ' . getUserTimezone());
date_add($next_object, date_interval_create_from_date_string('1 week'));
Find: Select
$prev_object = date_create($selected_date);
date_sub($prev_object, date_interval_create_from_date_string('1 week'));
Replace With: Select
$prev_object = date_create($selected_date . ' ' . getUserTimezone());
date_sub($prev_object, date_interval_create_from_date_string('1 week'));
Find: Select
$current_day_object = date_create(date_format($first_day_object, 'Y-m-d'));
Replace With: Select
$current_day_object = date_create(date_format($first_day_object, 'Y-m-d') . ' ' . getUserTimezone());
Find: Select
$start_object = date_create($start_date);
$end_object = date_create($end_date);
Replace With: Select
$start_object = date_create($start_date . ' ' . getUserTimezone());
$end_object = date_create($end_date . ' ' . getUserTimezone());
Find: Select
$d = date_parse(convertDateToEnglish($_POST['start_date']));
Replace With: Select
$d = date_parse(str_replace(',', '', convertDateToEnglish($_POST['start_date'])));
Find: Select
$d = date_parse(convertDateToEnglish($_POST['start_datetime']));
Replace With: Select
$d = date_parse(str_replace(',', '', convertDateToEnglish($_POST['start_datetime'])));
Find: Select
$start_string_parsed = date_parse(convertDateToEnglish($start_string));
Replace With: Select
$start_string_parsed = date_parse(str_replace(',', '', convertDateToEnglish($start_string)));
Find: Select
if ($start_string_parsed['year'] != false)
Replace With: Select
if ($start_string_parsed['year'] !== false)
Find: Select
if ($start_string_parsed['hour'] != false)
Replace With: Select
if ($start_string_parsed['hour'] !== false)
Find: Select
$end_string_parsed = date_parse(convertDateToEnglish($end_string));
Replace With: Select
$end_string_parsed = date_parse(str_replace(',', '', convertDateToEnglish($end_string)));
Find: Select
if ($end_string_parsed['year'] != false)
Replace With: Select
if ($end_string_parsed['year'] !== false)
Find: Select
if ($end_string_parsed['hour'] != false)
Replace With: Select
if ($end_string_parsed['hour'] !== false)

./Sources/Subs-Compat.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find (at the end of the file): Select
?>
Add Before: Select

/**
* Prevent fatal errors under PHP 8 when a disabled internal function is called.
*
* Before PHP 8, calling a disabled internal function merely generated a
* warning that could be easily suppressed by the @ operator. But as of PHP 8
* a disabled internal function is treated like it is undefined, which means
* a fatal error will be thrown and execution will halt. SMF expects the old
* behaviour, so these no-op polyfills make sure that is what happens.
*/
if (version_compare(PHP_VERSION, '8.0.0', '>='))
{
/*
* This array contains function names that meet the following conditions:
*
* 1. SMF assumes they are defined, even if disabled. Note that prior to
* PHP 8, this was always true for internal functions.
*
* 2. Some hosts are known to disable them.
*
* 3. SMF can get by without them (as opposed to missing functions that
* really SHOULD cause execution to halt).
*/
foreach (array('set_time_limit') as $func)
{
if (!function_exists($func))
eval('function ' . $func . '() { trigger_error("' . $func . '() has been disabled for security reasons", E_USER_WARNING); }');
}
unset($func);
}

./Sources/Subs-Editor.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
// Allow mods to modify BBC buttons.
Add Before: Select
// Define this here so mods can add to it via the hook.
$context['disabled_tags'] = array();

Find: Select
foreach ($editor_tag_map as $thisTag => $tagNameBBC)
Add Before: Select
if ($tag === 'float')
{
$context['disabled_tags']['floatleft'] = true;
$context['disabled_tags']['floatright'] = true;
}

Find: Select
if ((!empty($tag['code'])) && empty($context['disabled_tags'][$tag['code']]))
Replace With: Select
if (empty($tag['code']))
{
$context['bbc_toolbar'][$row][] = implode(',', $tagsRow);
$tagsRow = array();
}
elseif (empty($context['disabled_tags'][$tag['code']]))
Find: Select
$context['bbcodes_handlers'] .= '
});';
}
else
{
$context['bbc_toolbar'][$row][] = implode(',', $tagsRow);
$tagsRow = array();
}
Replace With: Select
$context['bbcodes_handlers'] .= '
});';
}
Find: Select
$row['answers'] = $smcFunc['json_decode']($row['answers'], true);
Replace With: Select
$row['answers'] = (array) $smcFunc['json_decode']($row['answers'], true);
Find: Select
$given_answer = trim($smcFunc['htmlspecialchars'](strtolower($_REQUEST[$verificationOptions['id'] . '_vv']['q'][$q])));
Replace With: Select
$given_answer = trim($smcFunc['htmlspecialchars']($smcFunc['strtolower']($_REQUEST[$verificationOptions['id'] . '_vv']['q'][$q])));
Find: Select
$versions = array('SMF 2.0');
Replace With: Select
$versions = array(SMF_FULL_VERSION);

./Sources/Subs-Graphics.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
if (!rename($fileName . '.tmp', $fileName))
return false;
Add After: Select


return true;
Find: Select
elseif (function_exists('imagejpeg'))
Add Before: Select
elseif (!empty($preferred_format) && ($preferred_format == 6) && function_exists('imagebmp'))
$success = imagebmp($dst_img, $destName);
elseif (!empty($preferred_format) && ($preferred_format == 15) && function_exists('imagewbmp'))
$success = imagewbmp($dst_img, $destName);

./Sources/Subs-Members.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3])) : $error[1];
Replace With: Select
$message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], (array) $error[3])) : $error[1];

./Sources/Subs-MessageIndex.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
SELECT c.name AS cat_name, c.id_cat, b.id_board, b.name AS board_name, b.child_level
Replace With: Select
SELECT c.name AS cat_name, c.id_cat, b.id_board, b.name AS board_name, b.child_level, b.redirect
Find: Select
'selected' => isset($boardListOptions['selected_board']) && $boardListOptions['selected_board'] == $row['id_board'],
Add Before: Select
'redirect' => $row['redirect'],

./Sources/Subs-Package.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$cdir = unpack('vdisk/@4/vdisk_entries/ventries/@12/Voffset', $data, $data_ecr + 4);
Replace With: Select
$cdir = unpack('vdisk/@4/vdisk_entries/ventries/@12/Voffset', substr($data, $data_ecr + 4, 16));
Find: Select
$header = unpack('Vcompressed_size/@8/vlen1/vlen2/vlen3/vdisk/@22/Voffset', $data, $pos_entry + 20);
Replace With: Select
$header = unpack('Vcompressed_size/@8/vlen1/vlen2/vlen3/vdisk/@22/Voffset', substr($data, $pos_entry + 20, 26));
Find: Select
$data,
$header['offset'] + 6
Replace With: Select
substr($data, $header['offset'] + 6, 24)
Find: Select
if (($general_purpose = unpack('Vcrc/Vcompressed_size/Vsize', $data, $gplen)) !== false)
Replace With: Select
if (($general_purpose = unpack('Vcrc/Vcompressed_size/Vsize', substr($data, $gplen, 12))) !== false)

./Sources/Subs-Sound.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
header('content-encoding: none');
Add Before: Select
header_remove('content-encoding');

./Sources/Subs-Timezones.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
'Pacific/Enderbury' => 'Pacific_Phoenix_Islands',
Replace With: Select
'Pacific/Kanton' => 'Pacific_Phoenix_Islands',
Find: Select
'Pacific/Kiritimati',
Add After: Select

'Pacific/Kanton',
Find: Select
'Pacific/Pohnpei' => array(
Add Before: Select
'Pacific/Kanton' => array(
array(
'ts' => PHP_INT_MIN,
'tzid' => 'Pacific/Enderbury',
),
),

./Sources/Subs.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
// Save whether $start was less than 0 or not.
Add After: Select

$start = (int) $start;
Find: Select
$context['current_page'] = $start / $num_per_page;
Replace With: Select
if (!isset($context['current_page']))
$context['current_page'] = $start / $num_per_page;
Find: Select
// A series of punctuation marks (except %), possibly separated by whitespace.
'~([^%\P{P}])(\s*)(?'.'>(\1|[^%\P{Po}])\s*(?!$))*~u',
Replace With: Select
// Repeated punctuation marks (except %), possibly separated by whitespace.
'~(?'.'>([^%\P{P}])\s*(?=\1))*~u',
'~([^%\P{P}])(?'.'>\1(?!$))*~u',
Find: Select
'~^\s*(?'.'>([\p{Pd}\p{Pe}\p{Pf}\p{Pc}]|[^%\P{Po}])\s*)*~u',
Add After: Select

// Runs of horizontal whitespace.
'~\s+~',
Find: Select

'$1$2',
Add Before: Select

'$1',
Find: Select
),
$format
Add Before: Select
' ',
Find: Select
call_integration_hook('integrate_pre_parsebbc', array(&$message, &$smileys, &$cache_id, &$parse_tags));
Replace With: Select
if ($message !== false)
call_integration_hook('integrate_pre_parsebbc', array(&$message, &$smileys, &$cache_id, &$parse_tags));
Find: Select
return $data = !empty($txt[$currentAttachment]) ? $txt[$currentAttachment] : $currentAttachment;
Replace With: Select
return $data = '<span style="display:inline-block" class="errorbox">' . (!empty($txt[$currentAttachment]) ? $txt[$currentAttachment] : $currentAttachment) . '</span>';
Find: Select
'href' => $scripturl . '?action=login' . $context['session_var'] . '=' . $context['session_id'],
Replace With: Select
'href' => $scripturl . '?action=logout;' . $context['session_var'] . '=' . $context['session_id'],
Find: Select
$statuses = array(
Add Before: Select
// This will fail anyways if headers have been sent.
if (headers_sent())
return;

./Sources/Who.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
$error_message = str_replace('"', '&quot;', empty($actions['error_params']) ? $txt[$actions['error']] : vsprintf($txt[$actions['error']], $actions['error_params']));
Replace With: Select
$error_message = str_replace('"', '&quot;', empty($actions['error_params']) ? $txt[$actions['error']] : vsprintf($txt[$actions['error']], (array) $actions['error_params']));
Find: Select
// Support Specialists
Add After: Select

'Doug Heffernan',

./Sources/tasks/CreatePost-Notify.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
'POSTERNAME' => un_htmlspecialchars($members_info[$posterOptions['id']]['name']),
Replace With: Select
'POSTERNAME' => un_htmlspecialchars(isset($members_info[$posterOptions['id']]['name']) ? $members_info[$posterOptions['id']]['name'] : $posterOptions['name']),

./Themes/default/Display.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
<img src="' . $attachment['href'] . ';image" alt="" width="' . $attachment['width'] . '" height="' . $attachment['height'] . '" loading="lazy" class="atc_img">';
Replace With: Select
<img src="' . $attachment['href'] . ';image" alt="" loading="lazy" class="atc_img">';

./Themes/default/MessageIndex.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
' . ($modSettings['pollMode'] == '1' ? '<span class="main_icons poll"></span> ' . $txt['poll'] : '') . '<br>
Replace With: Select
' . ($modSettings['pollMode'] == '1' ? '<span class="main_icons poll"></span> ' . $txt['poll'] . '<br>' : '') . '

./Themes/default/PersonalMessage.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
<a href="', $scripturl, '?action=pm" class="button">', $txt['inbox'], '</a>
Add After: Select

<a href="', $scripturl, '?action=pm;f=sent" class="button">', $txt['sent_items'], '</a>
Find: Select
<strong> ', $txt['on'], ':</strong> ', $message['time'], '
Replace With: Select
<strong> ', $txt['on'], ':</strong> ', $message['time'], '
Find: Select
<a href="', $scripturl, '?action=pm;f=', $context['folder'], ';start=', $context['start'], ';sort=name', $context['sort_by'] == 'name' && $context['sort_direction'] == 'up' ? ';desc' : '', $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', '">', ($context['from_or_to'] == 'from' ? $txt['from'] : $txt['to']), $context['sort_by'] == 'name' ? ' <span class="main_icons sort_' . $context['sort_direction'] . '"></span>' : '', '</a>
Replace With: Select
<a href="', $scripturl, '?action=pm;f=', $context['folder'], ';start=', $context['start'], ';sort=name', $context['sort_by'] == 'name' && $context['sort_direction'] == 'up' ? ';desc' : '', $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', '">', ($context['from_or_to'] == 'from' ? $txt['from'] : $txt['pm_to']), $context['sort_by'] == 'name' ? ' <span class="main_icons sort_' . $context['sort_direction'] . '"></span>' : '', '</a>
Find: Select
<div class="recipient_to"><strong>', $txt['to'], ':</strong> ', implode(', ', $draft['recipients']['to']), '</div>';
Replace With: Select
<div class="recipient_to"><strong>', $txt['pm_to'], ':</strong> ', implode(', ', $draft['recipients']['to']), '</div>';

./Themes/default/Post.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
', $txt['attached'], ':
Replace With: Select
', $txt['attachments'], ':
Find: Select
<strong>', $txt['attached'], ':</strong>
Replace With: Select
<strong>', $txt['attachments'], ':</strong>
Find: Select
<dl id="postAttachment2">
<dt>
', $txt['attach'], ':
</dt>
Replace With: Select
<dl id="postAttachment2">

./Themes/default/Profile.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
<td class="lefttext buddy_custom_fields">', $buddy['options'][$key], '</td>';
Replace With: Select
<td class="centertext buddy_custom_fields">', $buddy['options'][$key], '</td>';

./Themes/default/Xml.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select
<item type="board" id="', $board['id'], '" childlevel="', $board['child_level'], '"><![CDATA[', cleanXml($board['name']), ']]></item>';
Replace With: Select
<item type="board" id="', $board['id'], '" childlevel="', $board['child_level'], '" is_redirect="', (int) !empty($board['redirect']), '"><![CDATA[', cleanXml($board['name']), ']]></item>';

./Themes/default/css/index.css

Find: Select
.buttonlist .button {
margin-top: 2px;
margin-bottom: 2px;
}
.pagesection .button {
Replace With: Select
.pagesection .button {
Find: Select
}
.topic h4 {
Add Before: Select
overflow-wrap: break-word;
Find: Select
#post_settings, #postAttachment, #postAttachment2, #attachment_previews {
border-top: 1px solid #ddd;
margin: -1px 0 0 0;
Replace With: Select
#post_settings, #postAttachment, #postAttachment2, #attachment_previews {
Find: Select
.videocontainer video {
object-fit: contain;
background: black;
Add After: Select

max-width: 100%;

./Themes/default/index.template.php

This operation isn't vital to the installation of this mod.
Find: Select
* @version 2.1.0
Replace With: Select
* @version 2.1.2
Find: Select

<li class="button_signup">
Add Before: Select
';

if ($context['can_register'])
echo '
Find: Select
</li>
</ul>';
Replace With: Select
</li>';

echo '
</ul>';

./Themes/default/languages/Login.english.php

This operation isn't vital to the installation of this mod.
Find: Select
// Version: 2.1.0;
Replace With: Select
// Version: 2.1.2;
Find: Select
$txt['in_maintain_mode'] = 'This board is in Maintenance Mode.';
Replace With: Select
$txt['in_maintain_mode'] = 'This forum is in Maintenance Mode.';

./Themes/default/languages/Post.english.php

This operation isn't vital to the installation of this mod.
Find: Select
// Version: 2.1.0;
Replace With: Select
// Version: 2.1.2;
Find: Select
$txt['attach_restrict_attachmentPostLimit'] = 'maximum total size %1$d KB';
Replace With: Select
$txt['attach_restrict_attachmentPostLimit'] = 'maximum total size %1$s KB';
Find: Select
$txt['attach_restrict_attachmentPostLimit_MB'] = 'maximum total size %1$d MB';
Replace With: Select
$txt['attach_restrict_attachmentPostLimit_MB'] = 'maximum total size %1$s MB';
Find: Select
$txt['attach_restrict_attachmentSizeLimit'] = 'maximum individual size %1$d KB';
Replace With: Select
$txt['attach_restrict_attachmentSizeLimit'] = 'maximum individual size %1$s KB';
Find: Select
$txt['attach_restrict_attachmentSizeLimit_MB'] = 'maximum individual size %1$d MB';
Replace With: Select
$txt['attach_restrict_attachmentSizeLimit_MB'] = 'maximum individual size %1$s MB';
Find: Select
$txt['attach_remaining'] = '<span class="attach_remaining">%1$d</span> attachments remaining';
Replace With: Select
$txt['attach_remaining'] = '<span class="attach_remaining">%1$d</span> remaining';

./Themes/default/languages/Timezones.english.php

This operation isn't vital to the installation of this mod.
Find: Select
// Version: 2.1.0;
Replace With: Select
// Version: 2.1.2;
Find: Select
$txt['Pacific/Kiritimati'] = 'Kiritimati';
Add Before: Select
$txt['Pacific/Kanton'] = 'Canton Island';

./Themes/default/languages/index.english.php

This operation isn't vital to the installation of this mod.
Find: Select
// Version: 2.1.0;
Replace With: Select
// Version: 2.1.2;
Find: Select
$txt['attachments_not_allowed_to_see'] = 'You cannot see attachments on this board.';
Replace With: Select
$txt['attachments_not_allowed_to_see'] = 'You cannot view this attachment.';

./Themes/default/scripts/script.js

Find: Select
childLevel: parseInt($(this).attr('childlevel'))
Add Before: Select
isRedirect: parseInt($(this).attr('is_redirect')),
Find: Select
var iIndexPointer = 0;
Replace With: Select
// Don't do this twice.
$('#' + this.opt.sContainerId).off('mouseenter');
Find: Select
if (aBoardsAndCategories[i].isCategory)
oOption.disabled = 'disabled';
Replace With: Select
if (aBoardsAndCategories[i].isCategory || aBoardsAndCategories[i].isRedirect)
oOption.disabled = 'disabled';

./Themes/default/scripts/smf_fileUpload.js

Find: Select
// Show the drag-and-drop instructions and buttons
Add Before: Select
// Hide this, too. The progress bar does a better job.
$('.attach_available').remove();

Advertisement: