Permalink
Browse files

Importing SMF IPv6 mod

  • Loading branch information...
0 parents commit 36ad49f354a86d319901d907848fe75238146863 Jeremy D committed Sep 28, 2011
Showing with 841 additions and 0 deletions.
  1. +24 −0 LICENSE.txt
  2. +18 −0 README.txt
  3. +108 −0 database_install.php
  4. +56 −0 database_remove.php
  5. +618 −0 ipv6.xml
  6. +17 −0 package-info.xml
24 LICENSE.txt
@@ -0,0 +1,24 @@
+Copyright (c) 2011, SleePy (smf-mods-license@sleepycode.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the <organization> nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 README.txt
@@ -0,0 +1,18 @@
+IPv6 support for SMF 2.0+ Only. I will not backport these changes to 1.1.
+
+This customization will add support for the IPv6 enabled clients in SMF 2.0. Specifically posts, ip tracking and ban management have been changed. Member search from the admin panel does support this by default.
+
+Due to the size and necessity of the changes, please do not continue with installation if any change should fail the test. This may lead to unexpected results or a unusable forum.
+
+Note: During uninstallation, all IPv6 enabled bans will be disabled. This customization makes attempts to track those changes in columns it adds to the ban_items table. If you remove the database changes, this tracking will be lost. In addition upon reinstallation this customization makes attempts to re-enable those bans that should still be active.
+
+Note: Currently you are unable to link via iurl/url or auto linking ipv6 urls. This is due to the square brackets that ipv6 addresses are enclosed in. However this doesn't affect domains.
+
+Thanks to [url=http://www.soucy.org]Ray Soucy[/url]'s for his IPv6 functions he wrote and allowing usage of them in this customization.
+
+This customization is released under the BSD 3-Clause license. The terms of the license are including in this package (LICENSE.txt) or available on Simple Machines website at http://www.simplemachines.org/about/smf/license.php.
+
+ChangeLog:
+
+Version 1.0
+! Release
108 database_install.php
@@ -0,0 +1,108 @@
+<?php
+error_reporting(E_ALL);
+
+// Hopefully we have the goodies.
+if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF'))
+{
+ $using_ssi = true;
+ require_once(dirname(__FILE__) . '/SSI.php');
+}
+elseif (!defined('SMF'))
+ exit('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');
+
+global $db_prefix, $modSettings, $func, $smcFunc;
+
+// Fields to add
+$new_fields = array(
+ 'is_ipv6' => array('name'=> 'is_ipv6', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_low5' => array('name'=> 'ip_low5', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_high5' => array('name'=> 'ip_high5', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_low6' => array('name'=> 'ip_low6', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_high6' => array('name'=> 'ip_high6', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_low7' => array('name'=> 'ip_low7', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_high7' => array('name'=> 'ip_high7', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_low8' => array('name'=> 'ip_low8', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+ 'ip_high8' => array('name'=> 'ip_high8', 'type'=>'SMALLINT(255)', 'unsigned' => true, 'default' => 0),
+);
+
+$changed_fields = array(
+ 'ip_low1' => array('name'=> 'ip_low1', 'type'=>'SMALLINT(255)'),
+ 'ip_high1' => array('name'=> 'ip_high1', 'type'=>'SMALLINT(255)'),
+ 'ip_low2' => array('name'=> 'ip_low2', 'type'=>'SMALLINT(255)'),
+ 'ip_high2' => array('name'=> 'ip_high2', 'type'=>'SMALLINT(255)'),
+ 'ip_low3' => array('name'=> 'ip_low3', 'type'=>'SMALLINT(255)'),
+ 'ip_high3' => array('name'=> 'ip_high3', 'type'=>'SMALLINT(255)'),
+ 'ip_low4' => array('name'=> 'ip_low4', 'type'=>'SMALLINT(255)'),
+ 'ip_high4' => array('name'=> 'ip_high4', 'type'=>'SMALLINT(255)'),
+);
+
+// Load up the board info, we will only add these once.
+$table_columns = $smcFunc['db_list_columns']($db_prefix . 'ban_items');
+
+// Do the loopy, loop, loe.
+foreach ($new_fields as $column_name => $column_attributes)
+ if (!in_array($column_name, $table_columns))
+ $smcFunc['db_add_column']($db_prefix . 'ban_items', $column_attributes);
+
+// Do the loopy, loop, loe.
+foreach ($changed_fields as $column_name => $column_attributes)
+ $smcFunc['db_change_column']($db_prefix . 'ban_items', $column_attributes);
+
+// Find any IPv6 bans and reenable them again.
+// !!! Note, We changed is_ipv6 to the time stamp of when it is supposed of expired, 1 if it was a perm ban.
+$result = $smcFunc['db_query']('', '
+ SELECT id_ban_group, is_ipv6
+ FROM {db_prefix}ban_items
+ WHERE is_ipv6 < {int:is_ipv6}',
+ array(
+ 'is_ipv6' => '1'
+));
+
+$enabled_bans = array();
+$disabled_bans = array();
+$lost_bans = array();
+while ($row = $smcFunc['db_fetch_assoc']($request))
+{
+ if ($row['is_ipv6'] == 1)
+ $enabled_bans[] = $row['id_ban_group'];
+ elseif ($row['is_ipv6'] > 1 && time() < $row['is_ipv6'])
+ $enabled_bans[] = $row['id_ban_group'];
+ elseif ($row['is_ipv6'] > 1 && time() > $row['is_ipv6'])
+ $disabled_bans[] = $row['id_ban_group'];
+ // Where did you come from?
+ else
+ $lost_bans[] = $row['id_ban_group'];
+
+ // Not the best way, but will do the job.
+ $smcFunc['db_query']('', '
+ UPDATE {db_prefix}ban_groups
+ SET expire_time = {raw:expire}
+ WHERE id_ban_group = {int:ban_group}',
+ array(
+ 'expire' => $row['is_ipv6'] == 1 ? 'NULL' : $row['is_ipv6'],
+ 'ban_group' => $row['id_ban_group'],
+ ));
+}
+
+// Ok, We just re-enable these.
+$smcFunc['db_query']('', '
+ UPDATE {db_prefix}ban_items
+ SET is_ipv6 = {int:enabled}
+ WHERE is_ipv6 < {int:enabled}',
+ array(
+ 'enabled' => '1',
+));
+
+// Handle our lost bans.
+if (!empty($lost_bans) && !empty($using_ssi))
+ echo 'We had some bans that we could not properly enable. Please check these ban ids:', implode(', ', $lost_bans), '<br />';
+
+// For debugging/support purposes.
+if (!empty($lost_bans))
+log_error('Lost bans during IPV6 re-enabling:', implode(', ', $lost_bans), 'critical');
+
+// Update our ban time, forcing rechecks to occur.
+updateSettings(array('banLastUpdated' => time()));
+
+if(!empty($using_ssi))
+ echo 'If no errors, Success!';
56 database_remove.php
@@ -0,0 +1,56 @@
+<?php
+error_reporting(E_ALL);
+
+// Hopefully we have the goodies.
+if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF'))
+{
+ $using_ssi = true;
+ require_once(dirname(__FILE__) . '/SSI.php');
+}
+elseif (!defined('SMF'))
+ exit('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');
+
+global $db_prefix, $modSettings, $func, $smcFunc;
+
+// Find any IPv6 bans.
+$result = $smcFunc['db_query']('', '
+ SELECT bi.id_ban_group, bi.is_ipv6, bg.expire_time
+ FROM {db_prefix}ban_items AS bi
+ INNER JOIN {db_prefix}ban_groups AS bg ON (bi.id_ban_group = bg.id_ban_group)
+ WHERE bi.is_ipv6 = {int:is_ipv6}',
+ array(
+ 'is_ipv6' => '1'
+));
+
+$ipv6_bans = array();
+while($row = $smcFunc['db_fetch_assoc']($request))
+{
+ if ($row['expire_time'] != 'NULL')
+ $smcFunc['db_query']('', '
+ UPDATE {db_prefix}ban_items
+ SET is_ipv6 = {raw:expire_time}
+ WHERE id_ban_group = {int:ban_group}',
+ array(
+ 'expire_time' => $row['expire_time'],
+ 'ban_group' => $row['id_ban_group'],
+ ));
+
+ $ipv6_bans[] = $row['id_ban_group'];
+}
+
+// Do a mass update to disable these bans.
+$smcFunc['db_query']('', '
+ UPDATE {db_prefix}ban_groups
+ SET expire_time = {int:expired_time}
+ WHERE id_ban_group IN ({array_int:bans})',
+ array(
+ 'expired_time' => time() - 60, // 1 minute ago should do.
+ 'bans' => $ipv6_bans
+));
+
+// Update our ban time, forcing rechecks to occur.
+updateSettings(array('banLastUpdated' => time()));
+
+if(!empty($using_ssi))
+ echo 'If no errors, Success!';
+?>
618 ipv6.xml
@@ -0,0 +1,618 @@
+<?xml version="1.0"?>
+<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification">
+<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/">
+
+ <id>sleepy:ipv6_support</id>
+
+ <version>1.0</version>
+
+ <file name="$sourcedir/ManageSearchEngines.php">
+
+ <operation>
+
+ <search position="after"><![CDATA[ foreach ($spider_data as $spider)
+ {
+ // User agent is easy.
+]]></search>
+
+ <add><![CDATA[ // IPv6!!! I have no idea why we do a preg match when we already validated the ip in QueryString. I wont do it.
+ if (empty($ip_parts) && strpos($_SERVER['REMOTE_ADDR'], ':') !== false)
+ $ip_parts = smf_ipv6_to_ints($_SERVER['REMOTE_ADDR']);
+
+]]></add>
+
+ </operation>
+
+ </file>
+
+ <file name="$sourcedir/ManageBans.php">
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+
+ // Preset all values that are required.
+]]></search>
+
+ <add><![CDATA[ 'is_ipv6' => 0,
+ 'ip_low5' => 0,
+ 'ip_high5' => 0,
+ 'ip_low6' => 0,
+ 'ip_high6' => 0,
+ 'ip_low7' => 0,
+ 'ip_high7' => 0,
+ 'ip_low8' => 0,
+ 'ip_high8' => 0,
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+ }
+ else
+]]></search>
+
+ <add><![CDATA[ 'is_ipv6' => 'int',
+ 'ip_low5' => 'int',
+ 'ip_high5' => 'int',
+ 'ip_low6' => 'int',
+ 'ip_high6' => 'int',
+ 'ip_low7' => 'int',
+ 'ip_high7' => 'int',
+ 'ip_low8' => 'int',
+ 'ip_high8' => 'int',
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ ip_low4 = {int:ip_low4}, ip_high4 = {int:ip_high4}';
+]]></search>
+
+ <add><![CDATA[ ip_low4 = {int:ip_low4}, ip_high4 = {int:ip_high4},
+ is_ipv6 = {int:is_ipv6},
+ ip_low5 = {int:ip_low5}, ip_high5 = {int:ip_high5},
+ ip_low6 = {int:ip_low6}, ip_high6 = {int:ip_high6},
+ ip_low7 = {int:ip_low7}, ip_high7 = {int:ip_high7},
+ ip_low8 = {int:ip_low8}, ip_high8 = {int:ip_high8}';
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ $modlogInfo['ip_range'] = $_POST['ip'];
+ }
+ elseif ($_POST['bantype'] == 'hostname_ban')
+]]></search>
+
+ <add><![CDATA[ if (strpos($ip, ':') !== false)
+ $values['is_ipv6'] = 1;
+
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+
+ $ban_logs[] = array(
+]]></search>
+
+ <add><![CDATA[ !empty($ip_parts[4]['low']) ? 1 : 0,
+ $ip_parts[4]['low'],
+ $ip_parts[4]['high'],
+ $ip_parts[5]['low'],
+ $ip_parts[5]['high'],
+ $ip_parts[6]['low'],
+ $ip_parts[6]['high'],
+ $ip_parts[7]['low'],
+ $ip_parts[7]['high'],
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+ $ban_logs[] = array(
+ 'hostname' => $_POST['hostname'],
+]]></search>
+
+ <add><![CDATA[ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+ $ban_logs[] = array(
+ 'email' => $_POST['email'],
+]]></search>
+
+ <add><![CDATA[ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+ $ban_logs[] = array(
+ 'member' => $_POST['bannedUser'],
+]]></search>
+
+ <add><![CDATA[ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ if (count($ip_parts) != 4)
+]]></search>
+
+ <add><![CDATA[ if (count($ip_parts) != 4 || count($ip_parts) != 8)
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+ $ban_logs[] = array(
+ 'ip_range' => $ip,
+]]></search>
+
+ <add><![CDATA[ !empty($ip_parts[4]['low']) ? 1 : 0,
+ $ip_parts[4]['low'],
+ $ip_parts[4]['high'],
+ $ip_parts[5]['low'],
+ $ip_parts[5]['high'],
+ $ip_parts[6]['low'],
+ $ip_parts[6]['high'],
+ $ip_parts[7]['low'],
+ $ip_parts[7]['high'],
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ ),
+ $ban_triggers,
+ array('id_ban')
+]]></search>
+
+ <add><![CDATA[ 'is_ipv6' => 'int', 'ip_low5' => 'int', 'ip_high5' => 'int', 'ip_low6' => 'int', 'ip_high6' => 'int', 'ip_low7' => 'int', 'ip_high7' => 'int', 'ip_low8' => 'int', 'ip_high8' => 'int',
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes, bg.cannot_access, bg.cannot_register, bg.cannot_login, bg.cannot_post,
+ IFNULL(mem.id_member, 0) AS id_member, mem.member_name, mem.real_name
+ FROM {db_prefix}ban_groups AS bg
+]]></search>
+
+ <add><![CDATA[ bi.is_ipv6, bi.ip_low5, bi.ip_high5, bi.ip_low6, bi.ip_high6, bi.ip_low7, bi.ip_high7, bi.ip_low8, bi.ip_high8,
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ $context['ban_items'][$row['id_ban']]['ip'] = range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4']));
+]]></search>
+
+ <add><![CDATA[ $context['ban_items'][$row['id_ban']]['ip'] = range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4'] ,$row['ip_low5'], $row['ip_low6'], $row['ip_low7'], $row['ip_low8']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4'], $row['ip_high5'], $row['ip_high6'], $row['ip_high7'], $row['ip_high8']));
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ mem.member_name, mem.real_name
+ FROM {db_prefix}ban_items AS bi
+ LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member)
+]]></search>
+
+ <add><![CDATA[ bi.is_ipv6, bi.ip_low5, bi.ip_high5, bi.ip_low6, bi.ip_high6, bi.ip_low7, bi.ip_high7, bi.ip_low8, bi.ip_high8,
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ 'value' => empty($row['ip_low1']) ? '' : range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4'])),
+]]></search>
+
+ <add><![CDATA[ 'value' => empty($row['ip_low1']) ? '' : range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4'], $row['ip_low5'], $row['ip_low6'], $row['ip_low7'], $row['ip_low8']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4'], $row['ip_high5'], $row['ip_high6'], $row['ip_high7'], $row['ip_high8'])),
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ if (count($low) != 4 || count($high) != 4)
+ return '';
+
+]]></search>
+
+ <add><![CDATA[ // IPv6 check.
+ if (!empty($low[5]))
+ return range2ip_ipv6($low, $high);
+
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[function checkExistingTriggerIP($ip_array, $fullip = '')
+{
+ global $smcFunc, $scripturl;
+
+]]></search>
+
+ <add><![CDATA[function range2ip_ipv6($low, $high)
+{
+ if (count($low) != 8 || count($high) != 8)
+ return '';
+
+ $ip = array();
+ for ($i = 0; $i < 8; $i++)
+ {
+ if ($low[$i] == $high[$i])
+ $ip[$i] = dechex($low[$i]);
+ elseif ($low[$i] == '0' && $high[$i] == '255')
+ $ip[$i] = '*';
+ else
+ $ip[$i] = dechex($low[$i]) . '-' . dechex($high[$i]);
+ }
+
+ return implode(':', $ip);
+}
+
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ if (count($ip_array) == 4)
+]]></search>
+
+ <add><![CDATA[ if (count($ip_array) == 4 || count($ip_array) == 8)
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ );
+ else
+ return false;
+]]></search>
+
+ <add><![CDATA[ 'ip_low5' => $ip_array[4]['low'],
+ 'ip_high5' => $ip_array[4]['high'],
+ 'ip_low6' => $ip_array[5]['low'],
+ 'ip_high6' => $ip_array[5]['high'],
+ 'ip_low7' => $ip_array[6]['low'],
+ 'ip_high7' => $ip_array[6]['high'],
+ 'ip_low8' => $ip_array[7]['low'],
+ 'ip_high8' => $ip_array[7]['high'],
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ LIMIT 1',
+ $values
+ );
+]]></search>
+
+ <add><![CDATA[ AND ip_low5 = {int:ip_low5} AND ip_high5 = {int:ip_high5}
+ AND ip_low6 = {int:ip_low6} AND ip_high6 = {int:ip_high6}
+ AND ip_low7 = {int:ip_low7} AND ip_high7 = {int:ip_high7}
+ AND ip_low8 = {int:ip_low8} AND ip_high8 = {int:ip_high8}
+]]></add>
+
+ </operation>
+
+ </file>
+
+ <file name="$sourcedir/QueryString.php">
+
+ <operation>
+
+ <search position="replace"><![CDATA[ $_SERVER['REMOTE_ADDR'] = 'unknown';
+]]></search>
+
+ <add><![CDATA[ {
+ // !! ADDED
+ // Wait, maybe its IPv6? This is not pretty.
+ if (preg_match('~^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$~', $_SERVER['REMOTE_ADDR']) === 0)
+ $_SERVER['REMOTE_ADDR'] = 'unknown';
+ }
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_CLIENT_IP']) && (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['HTTP_CLIENT_IP']) == 0 || preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['REMOTE_ADDR']) != 0))
+]]></search>
+
+ <add><![CDATA[ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_CLIENT_IP']) && (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['HTTP_CLIENT_IP']) == 0 || preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['REMOTE_ADDR']) != 0))
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ if (!empty($_SERVER['HTTP_CLIENT_IP']) && (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['HTTP_CLIENT_IP']) == 0 || preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['REMOTE_ADDR']) != 0))
+]]></search>
+
+ <add><![CDATA[ if (!empty($_SERVER['HTTP_CLIENT_IP']) && (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['HTTP_CLIENT_IP']) == 0 || preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['REMOTE_ADDR']) != 0))
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ if (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $ip) != 0 && preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['REMOTE_ADDR']) == 0)
+]]></search>
+
+ <add><![CDATA[ if (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $ip) != 0 && preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['REMOTE_ADDR']) == 0)
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ elseif (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['HTTP_X_FORWARDED_FOR']) == 0 || preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown)~', $_SERVER['REMOTE_ADDR']) != 0)
+]]></search>
+
+ <add><![CDATA[ elseif (preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['HTTP_X_FORWARDED_FOR']) == 0 || preg_match('~^((0|10|172\.(1[6-9]|2[0-9]|3[01])|192\.168|255|127)\.|unknown|::1|fe80::|fc00::)~', $_SERVER['REMOTE_ADDR']) != 0)
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="replace"><![CDATA[ $_SERVER['BAN_CHECK_IP'] = '';
+]]></search>
+
+ <add><![CDATA[ {
+ // Wait, maybe its IPv6? This is not pretty.
+ if (preg_match('~^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$~', $_SERVER['BAN_CHECK_IP']) === 0)
+ $_SERVER['BAN_CHECK_IP'] = '';
+ }
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[?>
+]]></search>
+
+ <add><![CDATA[// Working with them as if they where IPv4 numbers, makes it SMF compatible.
+function smf_ipv6_to_ints($ip)
+{
+ // Expand the IP out.
+ $ip = explode(':', smf_ipv6_expand($ip));
+
+ $new_ip = array();
+ foreach ($ip as $int)
+ $new_ip[] = hexdec($int);
+
+ return implode($new_ip, '-');
+}
+
+
+/**
+ * IPv6 Address Functions for PHP
+ *
+ * Functions to manipulate IPv6 addresses for PHP
+ *
+ * Copyright (C) 2009 Ray Patrick Soucy
+ *
+ * LICENSE:
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package inet6
+ * @author Ray Soucy <rps@soucy.org>
+ * @version 1.0.1
+ * @copyright 2009 Ray Patrick Soucy
+ * @link http://www.soucy.org/
+ * @license GNU General Public License version 3 or later
+ * @since File available since Release 1.0.1
+ */
+function smf_ipv6_expand($addr, $strict_check = true)
+{
+ /* Check if there are segments missing, insert if necessary */
+ if (strpos($addr, '::') !== false)
+ {
+ $part = explode('::', $addr);
+ $part[0] = explode(':', $part[0]);
+ $part[1] = explode(':', $part[1]);
+ $missing = array();
+ for ($i = 0; $i < (8 - (count($part[0]) + count($part[1]))); $i++)
+ array_push($missing, '0000');
+ $missing = array_merge($part[0], $missing);
+ $part = array_merge($missing, $part[1]);
+ }
+ else
+ $part = explode(":", $addr);
+
+ /* Pad each segment until it has 4 digits */
+ foreach ($part as &$p)
+ while (strlen($p) < 4)
+ $p = '0' . $p;
+
+ unset($p);
+
+ /* Join segments */
+ $result = implode(':', $part);
+
+ /* Quick check to make sure the length is as expected */
+ if (!$strict_check || strlen($result) == 39)
+ return $result;
+ else
+ return false;
+}
+
+]]></add>
+
+ </operation>
+
+ </file>
+
+ <file name="$sourcedir/Security.php">
+
+ <operation>
+
+ <search position="after"><![CDATA[ // We use '255.255.255.255' for 'unknown' since it's not valid anyway.
+ elseif ($user_info['ip'] == 'unknown')
+ $ban_query[] = '(bi.ip_low1 = 255 AND bi.ip_high1 = 255
+]]></search>
+
+ <add><![CDATA[ // Again, the IP was validated, why use regex when we can split.
+ elseif (strpos($user_info[$ip_number], ':') !== false)
+ {
+ if ($ip_number == 'ip2' && $user_info['ip2'] == $user_info['ip'])
+ continue;
+
+ $ip_parts = array_map('hexdec', explode(':', smf_ipv6_expand($user_info[$ip_number])));
+
+ $ban_query[] = '((' . $ip_parts[0] . ' BETWEEN bi.ip_low1 AND bi.ip_high1)
+ AND (' . $ip_parts[1] . ' BETWEEN bi.ip_low2 AND bi.ip_high2)
+ AND (' . $ip_parts[2] . ' BETWEEN bi.ip_low3 AND bi.ip_high3)
+ AND (' . $ip_parts[3] . ' BETWEEN bi.ip_low4 AND bi.ip_high4)
+ AND (' . $ip_parts[4] . ' BETWEEN bi.ip_low5 AND bi.ip_high5)
+ AND (' . $ip_parts[5] . ' BETWEEN bi.ip_low6 AND bi.ip_high6)
+ AND (' . $ip_parts[6] . ' BETWEEN bi.ip_low7 AND bi.ip_high7)
+ AND (' . $ip_parts[7] . ' BETWEEN bi.ip_low8 AND bi.ip_high8))';
+
+ // IP was valid, maybe there's also a hostname...
+ if (empty($modSettings['disableHostnameLookup']))
+ {
+ $hostname = host_from_ip($user_info[$ip_number]);
+ if (strlen($hostname) > 0)
+ {
+ $ban_query[] = '({string:hostname} LIKE bi.hostname)';
+ $ban_query_vars['hostname'] = $hostname;
+ }
+ }
+ }
+]]></add>
+
+ </operation>
+
+ </file>
+
+ <file name="$sourcedir/Profile-View.php">
+
+ <operation>
+
+ <search position="replace"><![CDATA[ if (preg_match('/^\d{1,3}\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$/', $context['ip']) == 0)
+]]></search>
+
+ <add><![CDATA[ if (preg_match('/^\d{1,3}\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$/', $context['ip']) == 0 && preg_match('~^((([0-9A-Fa-f*]{1,4}:){7}[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){6}:[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){5}:([0-9A-Fa-f*]{1,4}:)?[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){4}:([0-9A-Fa-f*]{1,4}:){0,2}[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){3}:([0-9A-Fa-f*]{1,4}:){0,3}[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){2}:([0-9A-Fa-f*]{1,4}:){0,4}[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f*]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f*]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f*]{1,4}::([0-9A-Fa-f*]{1,4}:){0,5}[0-9A-Fa-f*]{1,4})|(::([0-9A-Fa-f*]{1,4}:){0,6}[0-9A-Fa-f*]{1,4})|(([0-9A-Fa-f*]{1,4}:){1,7}:))$~', $context['ip']) == 0)
+]]></add>
+
+ </operation>
+
+ </file>
+
+ <file name="$sourcedir/Subs.php">
+
+ <operation>
+
+ <search position="after"><![CDATA[ // Pretend that 'unknown' is 255.255.255.255. (since that can't be an IP anyway.)
+ if ($fullip == 'unknown')
+ $fullip = '255.255.255.255';
+]]></search>
+
+ <add><![CDATA[ if (strpos($fullip, ':') !== false)
+ return ip2range_ipv6($fullip);
+
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[ return $ip_array;
+}
+
+]]></search>
+
+ <add><![CDATA[
+ // Makes it simpiler to work with.
+ $ip_array[5] = array('low' => 0, 'high' => 0);
+ $ip_array[6] = array('low' => 0, 'high' => 0);
+ $ip_array[7] = array('low' => 0, 'high' => 0);
+ $ip_array[8] = array('low' => 0, 'high' => 0);
+
+]]></add>
+
+ </operation>
+
+ <operation>
+
+ <search position="after"><![CDATA[// Lookup an IP; try shell_exec first because we can do a timeout on it.
+function host_from_ip($ip)
+{]]></search>
+
+ <add><![CDATA[// Convert a single IPv6 to a ranged IPv6.
+function ip2range_ipv6($fullip)
+{
+ $ip_parts = explode(':', smf_ipv6_expand($fullip, false));
+ $ip_array = array();
+
+ if (count($ip_parts) != 8)
+ return array();
+
+ for ($i = 0; $i < 8; $i++)
+ {
+ if ($ip_parts[$i] == '*')
+ $ip_array[$i] = array('low' => '0', 'high' => hexdec('ffff'));
+ elseif (preg_match('/^([0-9A-Fa-f]{1,4})\-([0-9A-Fa-f]{1,4})$/', $ip_parts[$i], $range) == 1)
+ $ip_array[$i] = array('low' => hexdec($range[1]), 'high' => hexdec($range[2]));
+ elseif (is_numeric(hexdec($ip_parts[$i])))
+ $ip_array[$i] = array('low' => hexdec($ip_parts[$i]), 'high' => hexdec($ip_parts[$i]));
+ }
+
+ return $ip_array;
+}
+
+]]></add>
+
+ </operation>
+
+ </file>
+
+</modification>
17 package-info.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!DOCTYPE package-info SYSTEM "http://www.simplemachines.org/xml/package-info">
+<package-info xmlns="http://www.simplemachines.org/xml/package-info" xmlns:smf="http://www.simplemachines.org/">
+ <id>SleePy:ipv6_support</id>
+ <name>IPv6 Support</name>
+ <version>1.0</version>
+ <type>modification</type>
+ <install for="2.0-2.0.99">
+ <readme>README.txt</readme>
+ <modification>ipv6.xml</modification>
+ <database>database_install.php</database>
+ </install>
+ <uninstall for="2.0-2.0.99">
+ <modification reverse="true">ipv6.xml</modification>
+ <database>database_remove.php</database>
+ </uninstall>
+</package-info>

0 comments on commit 36ad49f

Please sign in to comment.