summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2006-03-11 19:57:52 +0100
committerAndreas Gohr <andi@splitbrain.org>2006-03-11 19:57:52 +0100
commit6d8affe6a4c62d13d1cd6051c23ab305145f9db6 (patch)
tree6dc7a98c995c8dda1c90322b47c16ca587b95950
parent21ed2ba400e22a21f7356caf84c837e7a724429e (diff)
downloadrpg-6d8affe6a4c62d13d1cd6051c23ab305145f9db6.tar.gz
rpg-6d8affe6a4c62d13d1cd6051c23ab305145f9db6.tar.bz2
enhanced clientIP() function
The function now can optinally return a single IP address and tries to be clever about which one to choose if multiple were supplied through X-Forwarded-For headers darcs-hash:20060311185752-7ad00-085bbed7eeffcff0be8f45417d73c13b733c4332.gz
-rw-r--r--_test/cases/inc/common_clientIP.test.php147
-rw-r--r--inc/common.php43
2 files changed, 184 insertions, 6 deletions
diff --git a/_test/cases/inc/common_clientIP.test.php b/_test/cases/inc/common_clientIP.test.php
new file mode 100644
index 000000000..257229811
--- /dev/null
+++ b/_test/cases/inc/common_clientIP.test.php
@@ -0,0 +1,147 @@
+<?php
+
+require_once DOKU_INC.'inc/init.php';
+require_once DOKU_INC.'inc/common.php';
+
+class common_clientIP_test extends UnitTestCase {
+
+ function test_simple_all(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_proxy1_all(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '77.77.77.77';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '';
+ $out = '123.123.123.123,77.77.77.77';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_proxy2_all(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77';
+ $out = '123.123.123.123,77.77.77.77';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_proxyhops_all(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77,66.66.66.66';
+ $out = '123.123.123.123,77.77.77.77,66.66.66.66';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_simple_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_proxy1_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '77.77.77.77';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '';
+ $out = '77.77.77.77';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_proxy2_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77';
+ $out = '77.77.77.77';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_proxyhops_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77,66.66.66.66';
+ $out = '66.66.66.66';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_local_all(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1';
+ $out = '123.123.123.123,127.0.0.1';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_local1_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_local2_single(){
+ $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '123.123.123.123';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_local3_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,10.0.0.1,192.168.0.2,172.17.1.1,172.21.1.1,172.31.1.1';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_local4_single(){
+ $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.0.5';
+ $out = '192.168.0.5';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_garbage_all(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_garbage_single(){
+ $_SERVER['REMOTE_ADDR'] = '123.123.123.123';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222';
+ $out = '123.123.123.123';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+ function test_garbageonly_all(){
+ $_SERVER['REMOTE_ADDR'] = 'argh';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222';
+ $out = '0.0.0.0';
+ $this->assertEqual(clientIP(),$out);
+ }
+
+ function test_garbageonly_single(){
+ $_SERVER['REMOTE_ADDR'] = 'argh';
+ $_SERVER['HTTP_X_REAL_IP'] = '';
+ $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222';
+ $out = '0.0.0.0';
+ $this->assertEqual(clientIP(true),$out);
+ }
+
+
+}
+
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/common.php b/inc/common.php
index 636b26f0b..ffb78f432 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -398,16 +398,47 @@ function checkwordblock(){
/**
* Return the IP of the client
*
- * Honours X-Forwarded-For Proxy Headers
+ * Honours X-Forwarded-For and X-Real-IP Proxy Headers
*
+ * It returns a comma separated list of IPs if the above mentioned
+ * headers are set. If the single parameter is set, it tries to return
+ * a routable public address, prefering the ones suplied in the X
+ * headers
+ *
+ * @param boolean $single If set only a single IP is returned
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function clientIP(){
- $my = $_SERVER['REMOTE_ADDR'];
- if($_SERVER['HTTP_X_FORWARDED_FOR']){
- $my .= ' ('.$_SERVER['HTTP_X_FORWARDED_FOR'].')';
+function clientIP($single=false){
+ $ip = array();
+ $ip[] = $_SERVER['REMOTE_ADDR'];
+ if($_SERVER['HTTP_X_FORWARDED_FOR'])
+ $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']));
+ if($_SERVER['HTTP_X_REAL_IP'])
+ $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_REAL_IP']));
+
+ // remove any non-IP stuff
+ $cnt = count($ip);
+ for($i=0; $i<$cnt; $i++){
+ $ip[$i] = preg_replace('/[^0-9\.]+/','',$ip[$i]);
+ if(!preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/',$ip[$i])) $ip[$i] = '';
+ if(empty($ip[$i])) unset($ip[$i]);
+ }
+ $ip = array_values(array_unique($ip));
+ if(!$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP
+
+ if(!$single) return join(',',$ip);
+
+ // decide which IP to use, trying to avoid local addresses
+ $ip = array_reverse($ip);
+ foreach($ip as $i){
+ if(preg_match('/^(127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$i)){
+ continue;
+ }else{
+ return $i;
+ }
}
- return $my;
+ // still here? just use the first (last) address
+ return $ip[0];
}
/**