Merge changes from 2.1-stable
diff --git a/system/core/Input.php b/system/core/Input.php
index 657fce6..4bb08f8 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -328,67 +328,66 @@
 			return $this->ip_address;
 		}
 
-		if (config_item('proxy_ips') != '' && $this->server('HTTP_X_FORWARDED_FOR') && $this->server('REMOTE_ADDR'))
+		$this->ip_address = $_SERVER['REMOTE_ADDR'];
+		$proxy_ips = config_item('proxy_ips');
+
+		if ( ! empty($proxy_ips))
 		{
-			$has_ranges = strpos($proxies, '/') !== FALSE;
-			$proxies = preg_split('/[\s,]/', config_item('proxy_ips'), -1, PREG_SPLIT_NO_EMPTY);
-			$proxies = is_array($proxies) ? $proxies : array($proxies);
-
-			if ($has_ranges)
+			foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)
 			{
-				$long_ip = ip2long($_SERVER['REMOTE_ADDR']);
-				$bit_32 = 1 << 32;
-
-				// Go through each of the IP Addresses to check for and
-				// test against range notation
-				foreach ($proxies as $ip)
+				if (($spoof = $this->server($header)) !== FALSE)
 				{
-					list($address, $mask_length) = explode('/', $ip, 2);
-
-					// Generate the bitmask for a 32 bit IP Address
-					$bitmask = $bit_32 - (1 << (32 - (int) $mask_length));
-					if (($long_ip & $bitmask) === $address)
+					// Some proxies typically list the whole chain of IP
+					// addresses through which the client has reached us.
+					// e.g. client_ip, proxy_ip1, proxy_ip2, etc.
+					if (strpos($spoof, ',') !== FALSE)
 					{
-						$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
+						$spoof = explode(',', $spoof, 2);
+						$spoof = $spoof[0];
+					}
+
+					if ( ! $this->valid_ip($spoof))
+					{
+						$spoof = FALSE;
+					}
+					else
+					{
 						break;
 					}
 				}
-
 			}
-			else
+
+			if ($spoof)
 			{
-				$this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies)
-					? $_SERVER['HTTP_X_FORWARDED_FOR']
-					: $_SERVER['REMOTE_ADDR'];
+				$has_ranges = (strpos($proxy_ips, '/') !== FALSE);
+				$proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));
+
+				if ($has_ranges)
+				{
+					$long_ip = ip2long($_SERVER['REMOTE_ADDR']);
+					$bit_32 = 1 << 32;
+
+					// Go through each of the IP Addresses to check for and
+					// test against range notation
+					foreach ($proxy_ips as $ip)
+					{
+						list($address, $mask_length) = explode('/', $ip, 2);
+
+						// Generate the bitmask for a 32 bit IP Address
+						$bitmask = $bit_32 - (1 << (32 - (int) $mask_length));
+						if (($long_ip & $bitmask) === $address)
+						{
+							$this->ip_address = $spoof;
+							break;
+						}
+					}
+				}
+				elseif (in_array($_SERVER['REMOTE_ADDR'], $proxy_ips, TRUE))
+				{
+					$this->ip_address = $spoof;
+				}
 			}
 		}
-		elseif ( ! $this->server('HTTP_CLIENT_IP') && $this->server('REMOTE_ADDR'))
-		{
-			$this->ip_address = $_SERVER['REMOTE_ADDR'];
-		}
-		elseif ($this->server('REMOTE_ADDR') && $this->server('HTTP_CLIENT_IP'))
-		{
-			$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
-		}
-		elseif ($this->server('HTTP_CLIENT_IP'))
-		{
-			$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
-		}
-		elseif ($this->server('HTTP_X_FORWARDED_FOR'))
-		{
-			$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
-		}
-
-		if ($this->ip_address === FALSE)
-		{
-			return $this->ip_address = '0.0.0.0';
-		}
-
-		if (strpos($this->ip_address, ',') !== FALSE)
-		{
-			$x = explode(',', $this->ip_address);
-			$this->ip_address = trim($x[0]);
-		}
 
 		if ( ! $this->valid_ip($this->ip_address))
 		{
@@ -545,7 +544,7 @@
 		$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
 
 		// CSRF Protection check
-		if ($this->_enable_csrf === TRUE)
+		if ($this->_enable_csrf === TRUE && ! $this->is_cli_request())
 		{
 			$this->security->csrf_verify();
 		}