Added option to disable IP-Logging
authorAlexander Ebert <ebert@woltlab.com>
Wed, 27 Jun 2012 15:58:52 +0000 (17:58 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 27 Jun 2012 15:59:22 +0000 (17:59 +0200)
IP-Logging can now be disabled through an option, the only exception is the session system which still stores IP addresses for security reasons. Since they usually get erased within a few hours this should be fine.

Additionally the blacklist now supports both IPv4 and IPv6 whereas all addresses are stored as IPv6 (faster checks on runtime), but IPv4 addresses will be still displayed as IPv4 (transparent conversion).

com.woltlab.wcf/option.xml
wcfsetup/install/files/lib/system/option/TextareaIpAddressOptionType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/UserUtil.class.php

index 00b1e2d44fcca233adfdcb6a64b3070db33e2e63..56e4ae08e9a8317c1d376db75dd9fbfe446e493c 100644 (file)
                                <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>
@@ -245,7 +251,7 @@ imagick:wcf.acp.option.image_adapter_type.imagick]]>
                        <!-- 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>
diff --git a/wcfsetup/install/files/lib/system/option/TextareaIpAddressOptionType.class.php b/wcfsetup/install/files/lib/system/option/TextareaIpAddressOptionType.class.php
new file mode 100644 (file)
index 0000000..4a5f4f5
--- /dev/null
@@ -0,0 +1,75 @@
+<?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;
+       }
+}
index 55e8114f56910eacddc41b9e0c5a2885fcf3ce6c..55d89359210fc27c79508cd3b8a12198be788adc 100644 (file)
@@ -143,6 +143,47 @@ final class UserUtil {
                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.
         *