¿Cómo obtener la dirección IP del cliente en PHP?


¿Cómo puedo obtener la dirección IP del cliente usando PHP?

Quiero mantener un registro del usuario que inició sesión en mi sitio web a través de su dirección IP.



Answers


Hagas lo que hagas, asegúrate de no confiar en los datos enviados por el cliente. $_SERVER['REMOTE_ADDR'] contiene la dirección IP real de la parte que se conecta. Ese es el valor más confiable que puede encontrar.

Sin embargo, pueden estar detrás de un servidor proxy en cuyo caso el proxy puede haber configurado $_SERVER['HTTP_X_FORWARDED_FOR'] , pero este valor se puede falsificar fácilmente. Por ejemplo, puede ser configurado por alguien sin un proxy, o la IP puede ser una IP interna de la LAN detrás del proxy.

Esto significa que si va a guardar $_SERVER['HTTP_X_FORWARDED_FOR'] , asegúrese de guardar también el $_SERVER['REMOTE_ADDR'] . Por ejemplo, guardando ambos valores en diferentes campos en su base de datos.

Si va a guardar la IP en una base de datos como una cadena, asegúrese de tener espacio para al menos 45 caracteres . IPv6 llegó para quedarse y esas direcciones son más grandes que las direcciones IPv4 anteriores.

(Tenga en cuenta que IPv6 generalmente usa 39 caracteres como máximo, pero también hay una notación IPv6 especial para direcciones IPv4 que en su forma completa puede tener hasta 45 caracteres. De modo que si sabe lo que está haciendo puede usar 39 caracteres, pero si solo quiero configurarlo y olvidarlo, use 45).




$_SERVER['REMOTE_ADDR'] puede que no contenga direcciones IP reales del cliente, ya que le dará una dirección proxy para clientes conectados a través de un proxy, por ejemplo. Eso bien puede ser lo que realmente quieres, dependiendo de lo que hagas con los IP. La dirección RFC1918 privada de alguien puede no servirle de nada, por ejemplo, tratando de ver de dónde se origina el tráfico, o recordando de qué IP se conectó el usuario por última vez, donde la IP pública del proxy o la puerta de enlace NAT podría ser más apropiado para almacenar

Hay varios encabezados HTTP como X-Forwarded-For que pueden o no ser configurados por varios proxies. El problema es que esos son simplemente encabezados HTTP que cualquier persona puede configurar. No hay garantía sobre su contenido. $_SERVER['REMOTE_ADDR'] es la dirección IP física real de la que el servidor web recibió la conexión y a la que se enviará la respuesta. Cualquier otra cosa es solo información arbitraria y voluntaria. Solo hay un escenario en el que puede confiar en esta información: está controlando el proxy que establece este encabezado. Es decir, solo si sabes al 100% dónde y cómo se configuró el encabezado, si lo haces por algo importante.

Habiendo dicho eso, aquí hay un código de muestra:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Nota del editor: Usar el código anterior tiene implicaciones de seguridad . El cliente puede configurar toda la información del encabezado HTTP (es decir, $_SERVER['HTTP_... ) a cualquier valor arbitrario que desee. Como tal, es mucho más confiable usar $_SERVER['REMOTE_ADDR'] , ya que el usuario no puede establecerlo.

De: http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html







Debería estar contenido en la variable $_SERVER['REMOTE_ADDR'] .




Aquí hay una muestra del código más limpio de una buena forma de obtener la ip del usuario.

$ip = $_SERVER['HTTP_CLIENT_IP']?$_SERVER['HTTP_CLIENT_IP']:($_SERVER['HTTP_X_FORWARDE‌​D_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR']);

Aquí hay una versión más corta que usa el operador elvis

$_SERVER['HTTP_CLIENT_IP']?:($_SERVER['HTTP_X_FORWARDE‌​D_FOR']?:$_SERVER['REMOTE_ADDR']);

Aquí hay una versión que usa isset para eliminar avisos (gracias, @shasi kanth)

$ip = isset($_SERVER['HTTP_CLIENT_IP'])?$_SERVER['HTTP_CLIENT_IP']‌:isset($_SERVER['HTT‌​P_X_FORWARDE‌​D_FOR'‌​])?$_SERVER['HTTP_X_‌​FORWARDED_FOR']:$_SE‌​RVER['REMOTE_ADDR']; 



Mi solución favorita es la forma en que Zend Framework 2 usa. También considera las propiedades $_SERVER HTTP_X_FORWARDED_FOR , HTTP_CLIENT_IP , HTTP_CLIENT_IP , pero declara una clase para que establezca algunos proxies de confianza y devuelve una dirección IP, no una matriz. Creo que esta es la solución que más se acerca:

class RemoteAddress
{
    /**
     * Whether to use proxy addresses or not.
     *
     * As default this setting is disabled - IP address is mostly needed to increase
     * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
     * just for more flexibility, but if user uses proxy to connect to trusted services
     * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
     *
     * @var bool
     */
    protected $useProxy = false;

    /**
     * List of trusted proxy IP addresses
     *
     * @var array
     */
    protected $trustedProxies = array();

    /**
     * HTTP header to introspect for proxies
     *
     * @var string
     */
    protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';

    // [...]

    /**
     * Returns client IP address.
     *
     * @return string IP address.
     */
    public function getIpAddress()
    {
        $ip = $this->getIpAddressFromProxy();
        if ($ip) {
            return $ip;
        }

        // direct IP address
        if (isset($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    /**
     * Attempt to get the IP address for a proxied client
     *
     * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
     * @return false|string
     */
    protected function getIpAddressFromProxy()
    {
        if (!$this->useProxy
            || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
        ) {
            return false;
        }

        $header = $this->proxyHeader;
        if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
            return false;
        }

        // Extract IPs
        $ips = explode(',', $_SERVER[$header]);
        // trim, so we can compare against trusted proxies properly
        $ips = array_map('trim', $ips);
        // remove trusted proxy IPs
        $ips = array_diff($ips, $this->trustedProxies);

        // Any left?
        if (empty($ips)) {
            return false;
        }

        // Since we've removed any known, trusted proxy servers, the right-most
        // address represents the first IP we do not know about -- i.e., we do
        // not know if it is a proxy server, or a client. As such, we treat it
        // as the originating IP.
        // @see http://en.wikipedia.org/wiki/X-Forwarded-For
        $ip = array_pop($ips);
        return $ip;
    }

    // [...]
}

Vea el código completo aquí: https://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php




Este es el método más avanzado que he encontrado, ya probé otros en el pasado. Válido para asegurarse de obtener la dirección IP del visitante (pero tenga en cuenta que cualquier hacker podría falsificar la dirección IP fácilmente).

function get_ip_address() {
    // check for shared internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

    // check for IPs passing through proxies
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        // check if multiple ips exist in var
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
            $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            foreach ($iplist as $ip) {
                if (validate_ip($ip))
                    return $ip;
            }
        } else {
            if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
        return $_SERVER['HTTP_X_FORWARDED'];
    if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
        return $_SERVER['HTTP_FORWARDED_FOR'];
    if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
        return $_SERVER['HTTP_FORWARDED'];

    // return unreliable ip since all else failed
    return $_SERVER['REMOTE_ADDR'];
}

/**
 * Ensures an ip address is both a valid IP and does not fall within
 * a private network range.
 */
function validate_ip($ip) {
    if (strtolower($ip) === 'unknown')
        return false;

    // generate ipv4 network address
    $ip = ip2long($ip);

    // if the ip is set and not equivalent to 255.255.255.255
    if ($ip !== false && $ip !== -1) {
        // make sure to get unsigned long representation of ip
        // due to discrepancies between 32 and 64 bit OSes and
        // signed numbers (ints default to signed in PHP)
        $ip = sprintf('%u', $ip);
        // do private network range checking
        if ($ip >= 0 && $ip <= 50331647) return false;
        if ($ip >= 167772160 && $ip <= 184549375) return false;
        if ($ip >= 2130706432 && $ip <= 2147483647) return false;
        if ($ip >= 2851995648 && $ip <= 2852061183) return false;
        if ($ip >= 2886729728 && $ip <= 2887778303) return false;
        if ($ip >= 3221225984 && $ip <= 3221226239) return false;
        if ($ip >= 3232235520 && $ip <= 3232301055) return false;
        if ($ip >= 4294967040) return false;
    }
    return true;
}

fuente: http://blackbe.lt/advanced-method-to-obtain-the-client-ip-in-php/




La respuesta es usar la variable $_SERVER . Por ejemplo, $_SERVER["REMOTE_ADDR"] devolvería la dirección IP del cliente.




Hay diferentes tipos de usuarios detrás de Internet, por lo que queremos captar la dirección IP de diferentes pociones. Que son,

1. $_SERVER['REMOTE_ADDR'] - Esto contiene la dirección IP real del cliente. Ese es el valor más confiable que puede encontrar del usuario.

2. $_SERVER['REMOTE_HOST'] - Esto obtendrá el nombre de Host desde el cual el usuario está viendo la página actual. Pero para que este script funcione, las búsquedas de nombres de host en el interior de httpd.conf deben configurarse.

3. $_SERVER['HTTP_CLIENT_IP'] - Esto $_SERVER['HTTP_CLIENT_IP'] la dirección IP cuando el usuario $_SERVER['HTTP_CLIENT_IP'] servicios compartidos de Internet.

4. $_SERVER['HTTP_X_FORWARDED_FOR'] - Esto obtendrá la dirección IP del usuario cuando esté detrás del proxy

Entonces podemos usar esta siguiente función combinada para obtener la dirección IP real de los usuarios que están viendo en diferentes posiciones,

// Function to get the user IP address
function getUserIP() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}



Como sé, la forma más sencilla de obtener la dirección IP del visitante / cliente es usar las variables $ _SERVER ['REMOTE_ADDR'] o $ _SERVER ['REMOTE_HOST'] .

Sin embargo, a veces esto no devuelve la dirección IP correcta del visitante, por lo que podemos utilizar algunas otras variables del servidor para obtener la dirección IP.

Las siguientes funciones son equivalentes con la diferencia solo en cómo y desde dónde se recuperan los valores.

getenv() se usa para obtener el valor de una variable de entorno en PHP.

// Function to get the client IP address

    function get_client_ip() {
    $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
       $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

$ _SERVER es una matriz que contiene variables de servidor creadas por el servidor web.

// Function to get the client IP address

    function get_client_ip() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}



Este es el método que uso y valida una entrada IPv4 :

// Get user IP address
if ( isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}

$ip = filter_var($ip, FILTER_VALIDATE_IP);
$ip = ($ip === false) ? '0.0.0.0' : $ip;



Me gusta este codenippet:

function getClientIP() {

    if (isset($_SERVER)) {

        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
            return $_SERVER["HTTP_X_FORWARDED_FOR"];

        if (isset($_SERVER["HTTP_CLIENT_IP"]))
            return $_SERVER["HTTP_CLIENT_IP"];

        return $_SERVER["REMOTE_ADDR"];
    }

    if (getenv('HTTP_X_FORWARDED_FOR'))
        return getenv('HTTP_X_FORWARDED_FOR');

    if (getenv('HTTP_CLIENT_IP'))
        return getenv('HTTP_CLIENT_IP');

    return getenv('REMOTE_ADDR');
}



$ip = "";

if (!empty($_SERVER["HTTP_CLIENT_IP"]))
{
 //check for ip from share internet
 $ip = $_SERVER["HTTP_CLIENT_IP"];
}
elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
 // Check for the Proxy User
 $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else
{
 $ip = $_SERVER["REMOTE_ADDR"];
}
echo $ip;



 $_SERVER['REMOTE_ADDR'];

prueba este




Bueno, esto se puede hacer simplemente usando la variable GLOBAL nombrada como $_SERVER .

$_SERVER es una matriz que tiene un nombre de atributo REMOTE_ADDR .

Simplemente $userIp = $_SERVER['REMOTE_ADDR']; como $userIp = $_SERVER['REMOTE_ADDR'];

o echo $_SERVER['REMOTE_ADDR']; directamente como echo $_SERVER['REMOTE_ADDR']; o echo ($_SERVER['REMOTE_ADDR']);




Como todos los demás dijeron antes, puede usar $_SERVER['REMOTE_ADDR']; para obtener la dirección IP del cliente.

Además, si necesita más información sobre un usuario, puede usar esto:

<?php
    $ip='0.0.0.0';
    $ip=$_SERVER['REMOTE_ADDR'];
    $clientDetails = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
    echo "You're logged in from: <b>" . $clientDetails->country . "</b>";
?>

La información más específica del cliente va en $ clientDetails.
Puede buscar elementos json almacenados en la variable $ clientDetails de esta manera: $ clientDetails-> PostalCode / hostname / region / loc ...

Estoy usando ipinfo.io para obtener información adicional.

Espero que ayude.




La siguiente función determina todas las posibilidades y devuelve el valor en coma separada (ip, ip, etc.).

También tiene la función de validación opcional como (primer parámetro que se deshabilitó de manera predeterminada) para validar la dirección IP en contra (Rango privado y Rango reservado).

<?php
echo GetClientIP(true);

function GetClientIP($validate = False){
  $ipkeys = array(
  'REMOTE_ADDR', 
  'HTTP_CLIENT_IP', 
  'HTTP_X_FORWARDED_FOR', 
  'HTTP_X_FORWARDED', 
  'HTTP_FORWARDED_FOR', 
  'HTTP_FORWARDED', 
  'HTTP_X_CLUSTER_CLIENT_IP'
  );

  /*
  now we check each key against $_SERVER if contain such value
  */
  $ip = array();
  foreach($ipkeys as $keyword){
    if( isset($_SERVER[$keyword]) ){
      if($validate){
        if( ValidatePublicIP($_SERVER[$keyword]) ){
          $ip[] = $_SERVER[$keyword];
        }
      }else{
        $ip[] = $_SERVER[$keyword];
      }
    }
  }

  $ip = ( empty($ip) ? 'Unknown' : implode(", ", $ip) );
  return $ip;

}
function ValidatePublicIP($ip){
  if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    return true;
  }
  else {
    return false;
  }
} 



Esta función es compacta y puede usarla en cualquier lugar. Pero !

¡No olvide esto! En este tipo, las funciones o los bloques de código no garantizan el registro de la IP real del usuario, ya que algunos usuarios pueden usar el proxy u otras puertas de enlace de forma segura para ser invisibles o no pueden rastrear.

Función Php:

function GetIP()
{
    if ( getenv("HTTP_CLIENT_IP") ) {
        $ip = getenv("HTTP_CLIENT_IP");
    } elseif ( getenv("HTTP_X_FORWARDED_FOR") ) {
        $ip = getenv("HTTP_X_FORWARDED_FOR");
        if ( strstr($ip, ',') ) {
            $tmp = explode(',', $ip);
            $ip = trim($tmp[0]);
        }
    } else {
        $ip = getenv("REMOTE_ADDR");
    }
    return $ip;
}

Uso:

$IP = GetIP(); o directamente GetIP();




function get_client_ip() 
{
   $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
       $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';

   return $ipaddress;
} 



¿¿¿¿Como eso????

if(($ip=filter_input(INPUT_SERVER,'REMOTE_ADDR',validate_ip))===false or empty($ip)){
  exit;
  }
echo $ip;

PD

if(($ip=filter_input(INPUT_SERVER,'REMOTE_ADDR',FILTER_VALIDATE_IP|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE))===false){
  header('HTTP/1.0 400 Bad Request');
  exit;
}

Todos los encabezados que comiencen con 'HTTP_' o 'X-' pueden ser falsos, respectivamente, definidos por el usuario. Si quieres hacer un seguimiento usa cooies, etc.




Aquí hay un trazador de líneas simple

$ip = $_SERVER['HTTP_X_FORWARDED_FOR']?: $_SERVER['HTTP_CLIENT_IP']?: $_SERVER['REMOTE_ADDR'];

EDITAR:

El código anterior puede devolver direcciones reservadas (como 10.0.0.1), una lista de direcciones de todos los servidores proxy en camino, etc. Para manejar estos casos, use el siguiente código:

function valid_ip($ip) {
    // for list of reserved IP addresses, see https://en.wikipedia.org/wiki/Reserved_IP_addresses
    return $ip && substr($ip, 0, 4) != '127.' && substr($ip, 0, 4) != '127.' && substr($ip, 0, 3) != '10.' && substr($ip, 0, 2) != '0.' ? $ip : false;
}

function get_client_ip() {
    // using explode to get only client ip from list of forwarders. see https://en.wikipedia.org/wiki/X-Forwarded-For
    return
    @$_SERVER['HTTP_X_FORWARDED_FOR'] ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2)[0] :
    @$_SERVER['HTTP_CLIENT_IP'] ? explode(',', $_SERVER['HTTP_CLIENT_IP'], 2)[0] :
    valid_ip(@$_SERVER['REMOTE_ADDR']) ?:
    'UNKNOWN';
}

echo get_client_ip();



$_SERVER['REMOTE_ADDR'];

Ejemplo:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}