mirror of
https://github.com/processwire/processwire.git
synced 2025-08-12 09:44:38 +02:00
Fix issue processwire/processwire-issues#957 add IPv6 address support for $session->getIP() method
This commit is contained in:
@@ -807,23 +807,26 @@ class Session extends Wire implements \IteratorAggregate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the IP address of the current user (IPv4)
|
* Get the IP address of the current user
|
||||||
*
|
*
|
||||||
* ~~~~~
|
* ~~~~~
|
||||||
* $ip = $session->getIP();
|
* $ip = $session->getIP();
|
||||||
* echo $ip; // outputs 111.222.333.444
|
* echo $ip; // outputs 111.222.333.444
|
||||||
* ~~~~~
|
* ~~~~~
|
||||||
*
|
*
|
||||||
* @param bool $int Return as a long integer for DB storage? (default=false)
|
* @param bool $int Return as a long integer? (default=false)
|
||||||
|
* - IPv6 addresses cannot be represented as an integer, so please note that using this int option makes it return a CRC32
|
||||||
|
* integer when using IPv6 addresses (3.0.184+).
|
||||||
* @param bool|int $useClient Give preference to client headers for IP? HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR (default=false)
|
* @param bool|int $useClient Give preference to client headers for IP? HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR (default=false)
|
||||||
* Specify integer 2 to include potential multiple CSV separated IPs (when provided by client).
|
* - Specify integer 2 to include potential multiple CSV separated IPs (when provided by client).
|
||||||
* @return string|int Returns string by default, or integer if $int argument indicates to.
|
* @return string|int Returns string by default, or integer if $int argument indicates to.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function getIP($int = false, $useClient = false) {
|
public function getIP($int = false, $useClient = false) {
|
||||||
|
|
||||||
$ip = $this->config->sessionForceIP;
|
$ip = $this->config->sessionForceIP;
|
||||||
|
$ipv6 = false;
|
||||||
|
|
||||||
if(!empty($ip)) {
|
if(!empty($ip)) {
|
||||||
// use IP address specified in $config->sessionForceIP and disregard other options
|
// use IP address specified in $config->sessionForceIP and disregard other options
|
||||||
$useClient = false;
|
$useClient = false;
|
||||||
@@ -831,44 +834,75 @@ class Session extends Wire implements \IteratorAggregate {
|
|||||||
} else if(empty($_SERVER['REMOTE_ADDR'])) {
|
} else if(empty($_SERVER['REMOTE_ADDR'])) {
|
||||||
// when accessing via CLI Interface, $_SERVER['REMOTE_ADDR'] isn't set and trying to get it, throws a php-notice
|
// when accessing via CLI Interface, $_SERVER['REMOTE_ADDR'] isn't set and trying to get it, throws a php-notice
|
||||||
$ip = '127.0.0.1';
|
$ip = '127.0.0.1';
|
||||||
|
|
||||||
} else if($useClient) {
|
} else if($useClient) {
|
||||||
if(!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP'];
|
if(!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||||
else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||||
else if(!empty($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
|
else if(!empty($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
|
||||||
else $ip = '0.0.0.0';
|
else $ip = '0.0.0.0';
|
||||||
// It's possible for X_FORWARDED_FOR to have more than one CSV separated IP address, per @tuomassalo
|
// It's possible for X_FORWARDED_FOR to have more than one CSV separated IP address, per @tuomassalo
|
||||||
if(strpos($ip, ',') !== false && $useClient !== 2) {
|
if(strpos($ip, ',') !== false && $useClient !== 2) {
|
||||||
list($ip) = explode(',', $ip);
|
list($ip) = explode(',', $ip);
|
||||||
}
|
}
|
||||||
// sanitize: if IP contains something other than digits, periods, commas, spaces,
|
// sanitize: if IP contains something other than digits, periods, commas, spaces,
|
||||||
// then don't use it and instead fallback to the REMOTE_ADDR.
|
// then don't use it and instead fallback to the REMOTE_ADDR.
|
||||||
$test = str_replace(array('.', ',', ' '), '', $ip);
|
$test = str_replace(array('.', ',', ' '), '', $ip);
|
||||||
if(!ctype_digit("$test")) $ip = $_SERVER['REMOTE_ADDR'];
|
if(!ctype_digit("$test")) {
|
||||||
|
if(strpos($test, ':') !== false) {
|
||||||
|
// ipv6 allowed
|
||||||
|
$test = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
|
||||||
|
$ip = $test === false ? $_SERVER['REMOTE_ADDR'] : $test;
|
||||||
|
} else {
|
||||||
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$ip = $_SERVER['REMOTE_ADDR'];
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(strpos($ip, ':') !== false) {
|
||||||
|
// attempt to identify an IPv4 version when an integer required for return value
|
||||||
|
if($int && $ip === '::1') {
|
||||||
|
$ip = '127.0.0.1';
|
||||||
|
} else if($int && strpos($ip, '.') && preg_match('!(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})!', $ip, $m)) {
|
||||||
|
$ip = $m[1]; // i.e. 0:0:0:0:0:ffff:192.1.56.10 => 192.1.56.10
|
||||||
|
} else {
|
||||||
|
$ipv6 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($useClient === 2 && strpos($ip, ',') !== false) {
|
if($useClient === 2 && strpos($ip, ',') !== false) {
|
||||||
// return multiple IPs
|
// return multiple IPs
|
||||||
$ips = explode(',', $ip);
|
$ips = array();
|
||||||
foreach($ips as $key => $ip) {
|
foreach(explode(',', $ip) as $ip) {
|
||||||
$ip = ip2long(trim($ip));
|
if($ipv6) {
|
||||||
if(!$int) $ip = long2ip($ip);
|
$ip = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
|
||||||
$ips[$key] = $ip;
|
if($ip !== false && $int) $ip = crc32($ip);
|
||||||
|
} else {
|
||||||
|
$ip = ip2long(trim($ip));
|
||||||
|
if(!$int) $ip = long2ip($ip);
|
||||||
|
}
|
||||||
|
if($ip !== false) $ips[] = $ip;
|
||||||
}
|
}
|
||||||
$ip = implode(',', $ips);
|
$ip = implode(',', $ips);
|
||||||
|
|
||||||
|
} else if($ipv6) {
|
||||||
|
$ip = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
|
||||||
|
if($ip === false) {
|
||||||
|
$ip = $int ? 0 : '0.0.0.0';
|
||||||
|
} else if($int) {
|
||||||
|
$ip = crc32($ip);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// sanitize by converting to and from integer
|
// sanitize by converting to and from integer
|
||||||
$ip = ip2long(trim($ip));
|
$ip = ip2long(trim($ip));
|
||||||
if(!$int) $ip = long2ip($ip);
|
if(!$int) $ip = long2ip($ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ip;
|
return $ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login a user with the given name and password
|
* Login a user with the given name and password
|
||||||
*
|
*
|
||||||
|
@@ -399,8 +399,10 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function getDatabaseSchema(Field $field) {
|
public function getDatabaseSchema(Field $field) {
|
||||||
|
|
||||||
|
$database = $this->wire()->database;
|
||||||
|
|
||||||
$maxIndexLength = $this->wire('database')->getMaxIndexLength();
|
$maxIndexLength = $database->getMaxIndexLength();
|
||||||
$websiteSchema = "varchar($maxIndexLength) NOT NULL default ''";
|
$websiteSchema = "varchar($maxIndexLength) NOT NULL default ''";
|
||||||
$parentSchema = "int unsigned NOT NULL default 0";
|
$parentSchema = "int unsigned NOT NULL default 0";
|
||||||
$flagSchema = "int unsigned NOT NULL default 0";
|
$flagSchema = "int unsigned NOT NULL default 0";
|
||||||
@@ -411,13 +413,13 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
$upvoteSchema = "int unsigned NOT NULL default 0";
|
$upvoteSchema = "int unsigned NOT NULL default 0";
|
||||||
$downvoteSchema = "int unsigned NOT NULL default 0";
|
$downvoteSchema = "int unsigned NOT NULL default 0";
|
||||||
$starsSchema = "tinyint unsigned default NULL";
|
$starsSchema = "tinyint unsigned default NULL";
|
||||||
|
$ipSchema = "varchar(45) NOT NULL default ''";
|
||||||
|
|
||||||
$schemaVersion = (int) $field->get('schemaVersion');
|
$schemaVersion = (int) $field->get('schemaVersion');
|
||||||
$updateSchema = true;
|
$updateSchema = true;
|
||||||
|
|
||||||
if(!$schemaVersion) {
|
if(!$schemaVersion) {
|
||||||
// add website field for PW 2.3+
|
// add website field for PW 2.3+
|
||||||
$database = $this->wire('database');
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
try {
|
try {
|
||||||
$database->query("ALTER TABLE `$table` ADD website $websiteSchema");
|
$database->query("ALTER TABLE `$table` ADD website $websiteSchema");
|
||||||
@@ -429,7 +431,6 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
|
|
||||||
if($schemaVersion < 2) {
|
if($schemaVersion < 2) {
|
||||||
// add parent_id and flags columns
|
// add parent_id and flags columns
|
||||||
$database = $this->wire('database');
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
try {
|
try {
|
||||||
$database->query("ALTER TABLE `$table` ADD parent_id $parentSchema");
|
$database->query("ALTER TABLE `$table` ADD parent_id $parentSchema");
|
||||||
@@ -442,7 +443,6 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
|
|
||||||
if($schemaVersion < 3) {
|
if($schemaVersion < 3) {
|
||||||
// add code column (admin code)
|
// add code column (admin code)
|
||||||
$database = $this->wire('database');
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
try {
|
try {
|
||||||
$database->query("ALTER TABLE `$table` ADD `code` $codeSchema");
|
$database->query("ALTER TABLE `$table` ADD `code` $codeSchema");
|
||||||
@@ -455,7 +455,6 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
|
|
||||||
if($schemaVersion < 4) {
|
if($schemaVersion < 4) {
|
||||||
// add subcode column (subscriber code)
|
// add subcode column (subscriber code)
|
||||||
$database = $this->wire('database');
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
try {
|
try {
|
||||||
$database->query("ALTER TABLE `$table` ADD `subcode` $subcodeSchema");
|
$database->query("ALTER TABLE `$table` ADD `subcode` $subcodeSchema");
|
||||||
@@ -468,7 +467,6 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
|
|
||||||
if($schemaVersion < 5 && $updateSchema) {
|
if($schemaVersion < 5 && $updateSchema) {
|
||||||
// add upvote/downvote columns
|
// add upvote/downvote columns
|
||||||
$database = $this->wire('database');
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
$parentSchema = parent::getDatabaseSchema($field);
|
$parentSchema = parent::getDatabaseSchema($field);
|
||||||
try {
|
try {
|
||||||
@@ -477,7 +475,7 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
`comment_id` int unsigned NOT NULL,
|
`comment_id` int unsigned NOT NULL,
|
||||||
`vote` tinyint NOT NULL,
|
`vote` tinyint NOT NULL,
|
||||||
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`ip` VARCHAR(15) NOT NULL default '',
|
`ip` $ipSchema,
|
||||||
`user_id` int unsigned NOT NULL default 0,
|
`user_id` int unsigned NOT NULL default 0,
|
||||||
PRIMARY KEY (`comment_id`, `ip`, `vote`),
|
PRIMARY KEY (`comment_id`, `ip`, `vote`),
|
||||||
INDEX `created` (`created`)
|
INDEX `created` (`created`)
|
||||||
@@ -506,7 +504,6 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($schemaVersion < 6 && $updateSchema) {
|
if($schemaVersion < 6 && $updateSchema) {
|
||||||
$database = $this->wire('database');
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
try {
|
try {
|
||||||
$database->query("ALTER TABLE `$table` ADD `stars` $starsSchema");
|
$database->query("ALTER TABLE `$table` ADD `stars` $starsSchema");
|
||||||
@@ -520,6 +517,17 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($schemaVersion < 7 && $updateSchema) {
|
||||||
|
$table = $database->escapeTable($field->getTable());
|
||||||
|
try {
|
||||||
|
$database->query("ALTER TABLE `$table` MODIFY `ip` $ipSchema");
|
||||||
|
$database->query("ALTER TABLE `{$table}_votes` MODIFY `ip` $ipSchema");
|
||||||
|
$schemaVersion = 7;
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$this->error($e->getMessage(), Notice::debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$_schemaVersion = (int) $field->get('schemaVersion');
|
$_schemaVersion = (int) $field->get('schemaVersion');
|
||||||
if($_schemaVersion < $schemaVersion) {
|
if($_schemaVersion < $schemaVersion) {
|
||||||
@@ -538,7 +546,7 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
$schema['sort'] = "int unsigned NOT NULL";
|
$schema['sort'] = "int unsigned NOT NULL";
|
||||||
$schema['created'] = "int unsigned NOT NULL";
|
$schema['created'] = "int unsigned NOT NULL";
|
||||||
$schema['created_users_id'] = "int unsigned NOT NULL";
|
$schema['created_users_id'] = "int unsigned NOT NULL";
|
||||||
$schema['ip'] = "varchar(15) NOT NULL default ''";
|
$schema['ip'] = $ipSchema;
|
||||||
$schema['user_agent'] = "varchar($maxIndexLength) NOT NULL default ''";
|
$schema['user_agent'] = "varchar($maxIndexLength) NOT NULL default ''";
|
||||||
|
|
||||||
$schemaVersion = $field->get('schemaVersion');
|
$schemaVersion = $field->get('schemaVersion');
|
||||||
|
Reference in New Issue
Block a user