You are here

public function IP2Location::lookup in Smart IP 6

Same name and namespace in other branches
  1. 7 includes/IP2Location.inc \IP2Location::lookup()

File

includes/IP2Location.inc, line 303

Class

IP2Location

Code

public function lookup($ip, $field = self::ALL) {
  $keys = array_keys($this->columns);

  // Get record by single field name
  if ($field != self::ALL) {
    if ($this->columns[$keys[$field - 1]][$this->db['type']] == 0) {
      return str_replace('%TYPE%', $this->db['type'], self::FIELD_NOT_SUPPORTED);
    }
  }
  $result = new IP2LocationRecord();
  $result->ipAddress = $ip;

  // IPv4 database
  if ($this->db['ip_version'] == self::IPV4) {
    if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
      if ($field != self::ALL) {
        return self::INVALID_IPV4;
      }
      else {
        $result->countryCode = $result->countryName = $result->regionName = $result->cityName = $result->latitude = $result->longitude = $result->isp = $result->domainName = $result->zipCode = $result->timeZone = $result->netSpeed = $result->iddCode = $result->areaCode = $result->weatherStationCode = $result->weatherStationName = $result->mcc = $result->mnc = $result->mobileCarrierName = $result->elevation = $result->usageType = self::INVALID_IPV4;
        return $result;
      }
    }
    $ipNumber = sprintf('%u', ip2long($ip));
    $ipNumber = $ipNumber >= 4294967295 ? $ipNumber - 1 : $ipNumber;
  }
  else {
    if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
      if ($field != self::ALL) {
        return self::INVALID_IPV6;
      }
      else {
        $result->countryCode = $result->countryName = $result->regionName = $result->cityName = $result->latitude = $result->longitude = $result->isp = $result->domainName = $result->zipCode = $result->timeZone = $result->netSpeed = $result->iddCode = $result->areaCode = $result->weatherStationCode = $result->weatherStationName = $result->mcc = $result->mnc = $result->mobileCarrierName = $result->elevation = $result->usageType = self::INVALID_IPV6;
        return $result;
      }
    }
    $ipNumber = $this
      ->ipv6ToLong($ip);
    $ipNumber = bccomp($ipNumber, 3.402823669209385E+38) == 0 ? bcsub($ipNumber, 1) : $ipNumber;
  }
  $result->ipNumber = $ipNumber;
  $low = 0;
  $high = $this->db['count'];
  $mid = 0;
  $ipFrom = 0;
  $ipTo = 0;
  while ($low <= $high) {
    $mid = (int) (($low + $high) / 2);
    $ipFrom = $this
      ->readByte($this->db['base_address'] + $mid * $this->db['column'] * 4, '32');
    $ipTo = $this
      ->readByte($this->db['base_address'] + ($mid + 1) * $this->db['column'] * 4, '32');
    if ($ipFrom < 0) {
      $ipFrom += pow(2, 32);
    }
    if ($ipTo < 0) {
      $ipTo += pow(2, 32);
    }
    if ($ipNumber >= $ipFrom && $ipNumber < $ipTo) {
      $offset = $this->db['base_address'] + $mid * $this->db['column'] * 4;
      switch ($field) {
        case self::COUNTRY_CODE:
        case self::REGION_NAME:
        case self::CITY_NAME:
        case self::ISP:
        case self::DOMAIN_NAME:
        case self::ZIP_CODE:
        case self::TIME_ZONE:
        case self::NET_SPEED:
        case self::IDD_CODE:
        case self::AREA_CODE:
        case self::WEATHER_STATION_CODE:
        case self::WEATHER_STATION_NAME:
        case self::MCC:
        case self::MNC:
        case self::MOBILE_CARRIER_NAME:
        case self::ELEVATION:
          return $this
            ->readByte($this
            ->readByte($offset + 4 * ($this->columns[$keys[$field - 1]][$this->db['type']] - 1), '32'), 'string', true);
        case self::COUNTRY_NAME:
          return $this
            ->readByte($this
            ->readByte($offset + 4 * ($this->columns[$keys[$field - 1]][$this->db['type']] - 1), '32') + 3, 'string', true);
        case self::LATITUDE:
        case self::LONGITUDE:
          return $this
            ->readByte($offset + 4 * ($this->columns[$keys[$field - 1]][$this->db['type']] - 1), 'float', true);
        case self::USAGE_TYPE:
          return $this
            ->readByte($this
            ->readByte($offset + 4 * ($this->columns[$keys[$field - 1]][$this->db['type']] - 1), '32'), 'string', true);
        default:
          $result->regionName = $result->cityName = $result->latitude = $result->longitude = $result->isp = $result->domainName = $result->zipCode = $result->timeZone = $result->netSpeed = $result->iddCode = $result->areaCode = $result->weatherStationCode = $result->weatherStationName = $result->mcc = $result->mnc = $result->mobileCarrierName = $result->elevation = $result->usageType = str_replace('%TYPE%', $this->db['type'], self::FIELD_NOT_SUPPORTED);
          $result->countryCode = $this
            ->readByte($this
            ->readByte($offset + 4 * ($this->columns[$keys[self::COUNTRY_CODE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          $result->countryName = $this
            ->readByte($this
            ->readByte($offset + 4 * ($this->columns[$keys[self::COUNTRY_NAME - 1]][$this->db['type']] - 1), '32') + 3, 'string', true);
          if ($this->columns[$keys[self::REGION_NAME - 1]][$this->db['type']] != 0) {
            $result->regionName = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::REGION_NAME - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::CITY_NAME - 1]][$this->db['type']] != 0) {
            $result->cityName = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::CITY_NAME - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::LATITUDE - 1]][$this->db['type']] != 0) {
            $result->latitude = $this
              ->readByte($offset + 4 * ($this->columns[$keys[self::LATITUDE - 1]][$this->db['type']] - 1), 'float', true);
          }
          if ($this->columns[$keys[self::LONGITUDE - 1]][$this->db['type']] != 0) {
            $result->longitude = $this
              ->readByte($offset + 4 * ($this->columns[$keys[self::LONGITUDE - 1]][$this->db['type']] - 1), 'float', true);
          }
          if ($this->columns[$keys[self::ISP - 1]][$this->db['type']] != 0) {
            $result->isp = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::ISP - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::DOMAIN_NAME - 1]][$this->db['type']] != 0) {
            $result->domainName = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::DOMAIN_NAME - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::ZIP_CODE - 1]][$this->db['type']] != 0) {
            $result->zipCode = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::ZIP_CODE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::TIME_ZONE - 1]][$this->db['type']] != 0) {
            $result->timeZone = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::TIME_ZONE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::NET_SPEED - 1]][$this->db['type']] != 0) {
            $result->netSpeed = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::NET_SPEED - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::IDD_CODE - 1]][$this->db['type']] != 0) {
            $result->iddCode = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::IDD_CODE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::AREA_CODE - 1]][$this->db['type']] != 0) {
            $result->areaCode = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::AREA_CODE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::WEATHER_STATION_CODE - 1]][$this->db['type']] != 0) {
            $result->weatherStationCode = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::WEATHER_STATION_CODE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::WEATHER_STATION_NAME - 1]][$this->db['type']] != 0) {
            $result->weatherStationName = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::WEATHER_STATION_NAME - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::MCC - 1]][$this->db['type']] != 0) {
            $result->mcc = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::MCC - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::MNC - 1]][$this->db['type']] != 0) {
            $result->mnc = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::MNC - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::MOBILE_CARRIER_NAME - 1]][$this->db['type']] != 0) {
            $result->mobileCarrierName = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::MOBILE_CARRIER_NAME - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::ELEVATION - 1]][$this->db['type']] != 0) {
            $result->elevation = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::ELEVATION - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          if ($this->columns[$keys[self::USAGE_TYPE - 1]][$this->db['type']] != 0) {
            $result->usageType = $this
              ->readByte($this
              ->readByte($offset + 4 * ($this->columns[$keys[self::USAGE_TYPE - 1]][$this->db['type']] - 1), '32'), 'string', true);
          }
          return $result;
      }
    }
    else {
      if ($ipNumber < $ipFrom) {
        $high = $mid - 1;
      }
      else {
        $low = $mid + 1;
      }
    }
  }
}