<defaultvalue>1</defaultvalue>
</option>
+ <option name="log_ip_address">
+ <categoryname>module.system</categoryname>
+ <optiontype>boolean</optiontype>
+ <defaultvalue>1</defaultvalue>
+ </option>
+
<!-- general.page -->
<option name="page_title">
<categoryname>general.page</categoryname>
<!-- security.blacklist -->
<option name="blacklist_ip_addresses">
<categoryname>security.blacklist</categoryname>
- <optiontype>textarea</optiontype>
+ <optiontype>textareaIpAddress</optiontype>
</option>
<option name="blacklist_user_agents">
<categoryname>security.blacklist</categoryname>
--- /dev/null
+<?php
+namespace wcf\system\option;
+use wcf\data\option\Option;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\UserUtil;
+
+/**
+ * TextareaIpAddressOptionType is an implementation of IOptionType for 'textarea' tags with IPv4/IPv6 support.
+ * IP-Addresses will be converted into IPv6 upon saving but will be displayed as IPv4 whenever applicable.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2012 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.option
+ * @category Community Framework
+ */
+class TextareaIpAddressOptionType extends TextOptionType {
+ /**
+ * @see wcf\system\option\IOptionType::getFormElement()
+ */
+ public function getFormElement(Option $option, $value) {
+ if (!empty($value)) {
+ $ips = explode("\n", $value);
+ foreach ($ips as &$ip) {
+ $ip = UserUtil::convertIPv6To4($ip);
+ }
+ unset($ip);
+
+ $value = implode("\n", $ips);
+ }
+
+ WCF::getTPL()->assign(array(
+ 'option' => $option,
+ 'value' => $value
+ ));
+ return WCF::getTPL()->fetch('textareaOptionType');
+ }
+
+ /**
+ * @see wcf\system\option\IOptionType::validate()
+ */
+ public function validate(Option $option, $newValue) {
+ if (!empty($newValue)) {
+ $ips = explode("\n", $newValue);
+ foreach ($ips as $ip) {
+ $ip = trim($ip);
+
+ $ip = UserUtil::convertIPv6To4($ip);
+ if (empty($ip)) {
+ throw new UserInputException($option->optionName, 'validationFailed');
+ }
+ }
+ }
+ }
+
+ /**
+ * @see wcf\system\option\IOptionType::getData()
+ */
+ public function getData(Option $option, $newValue) {
+ if (!empty($newValue)) {
+ $ips = explode("\n", $newValue);
+ foreach ($ips as &$ip) {
+ $ip = trim($ip);
+ $ip = UserUtil::convertIPv4To6($ip);
+ }
+ unset($ip);
+
+ $newValue = implode("\n", $ips);
+ }
+
+ return $newValue;
+ }
+}
return '::ffff:'.$part7.':'.$part8;
}
+ /**
+ * Converts IPv6 embedded IPv4 address into IPv4 or returns input if true IPv6.
+ *
+ * @param string $ip
+ * @return string
+ */
+ public static function convertIPv6To4($ip) {
+ // validate if given IP is a proper IPv6 address
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
+ // validate if given IP is a proper IPv4 address
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
+ // TODO: Use an exception instead?
+ // ip address is invalid
+ return '';
+ }
+
+ return $ip;
+ }
+
+ // check if ip is a masked IPv4 address
+ if (substr($ip, 0, 7) == '::ffff:') {
+ $ip = explode(':', substr($ip, 7));
+ $ip[0] = base_convert($ip[0], 16, 10);
+ $ip[1] = base_convert($ip[1], 16, 10);
+
+ $ipParts = array();
+ $tmp = $ip[0] % 256;
+ $ipParts[] = ($ip[0] - $tmp) / 256;
+ $ipParts[] = $tmp;
+ $tmp = $ip[1] % 256;
+ $ipParts[] = ($ip[1] - $tmp) / 256;
+ $ipParts[] = $tmp;
+
+ return implode('.', $ipParts);
+ }
+ else {
+ // given ip is an IPv6 address and cannot be converted
+ return $ip;
+ }
+ }
+
/**
* Returns the request uri of the active request.
*