public function lookup()

in proxy-chooser/classes/IP2Location.php [944:1250]


	public function lookup($ip, $fields = null, $asNamed = true)
	{
		// extract IP version and number
		list($ipVersion, $ipNumber) = self::ipVersionAndNumber($ip);
		// perform the binary search proper (if the IP address was invalid, binSearch will return false)
		$pointer = $this->binSearch($ipVersion, $ipNumber);
		if (empty($pointer)) {
			return false;
		}

		// apply defaults if needed
		if ($fields === null) {
			$fields = $this->defaultFields;
		}

		// Get the entire row based on the pointer value
		// The length of the row differs based on the IP version
		if ($ipVersion === 4) {
			$this->rawPositionsRow = $this->read($pointer - 1, $this->columnWidth[4] + 4);
		} elseif ($ipVersion === 6) {
			$this->rawPositionsRow = $this->read($pointer - 1, $this->columnWidth[6]);
		}

		// turn fields into an array in case it wasn't already
		$ifields = (array) $fields;

		// add fields if needed
		if (\in_array(self::ALL, $ifields)) {
			$ifields[] = self::REGION_NAME;
			$ifields[] = self::CITY_NAME;
			$ifields[] = self::ISP;
			$ifields[] = self::DOMAIN_NAME;
			$ifields[] = self::ZIP_CODE;
			$ifields[] = self::TIME_ZONE;
			$ifields[] = self::NET_SPEED;
			$ifields[] = self::ELEVATION;
			$ifields[] = self::USAGE_TYPE;

			$ifields[] = self::COUNTRY;
			$ifields[] = self::COORDINATES;
			$ifields[] = self::IDD_AREA;
			$ifields[] = self::WEATHER_STATION;
			$ifields[] = self::MCC_MNC_MOBILE_CARRIER_NAME;

			$ifields[] = self::IP_ADDRESS;
			$ifields[] = self::IP_VERSION;
			$ifields[] = self::IP_NUMBER;
		}
		// turn into a uniquely-valued array the fast way
		// (see: http://php.net/manual/en/function.array-unique.php#77743)
		$afields = array_keys(array_flip($ifields));
		// sorting them in reverse order warrants that by the time we get to
		// SINGULAR fields, its MULTIPLE counterparts, if at all present, have
		// already been retrieved
		rsort($afields);

		// maintain a list of already retrieved fields to avoid doing it twice
		$done = [
		self::COUNTRY_CODE         => false,
		self::COUNTRY_NAME         => false,
		self::REGION_NAME          => false,
		self::CITY_NAME            => false,
		self::LATITUDE             => false,
		self::LONGITUDE            => false,
		self::ISP                  => false,
		self::DOMAIN_NAME          => false,
		self::ZIP_CODE             => false,
		self::TIME_ZONE            => false,
		self::NET_SPEED            => false,
		self::IDD_CODE             => false,
		self::AREA_CODE            => false,
		self::WEATHER_STATION_CODE => false,
		self::WEATHER_STATION_NAME => false,
		self::MCC                  => false,
		self::MNC                  => false,
		self::MOBILE_CARRIER_NAME  => false,
		self::ELEVATION            => false,
		self::USAGE_TYPE           => false,

		self::COUNTRY                     => false,
		self::COORDINATES                 => false,
		self::IDD_AREA                    => false,
		self::WEATHER_STATION             => false,
		self::MCC_MNC_MOBILE_CARRIER_NAME => false,

		self::IP_ADDRESS => false,
		self::IP_VERSION => false,
		self::IP_NUMBER  => false,
	];
		// results are empty to begin with
		$results = [];

		// treat each field in turn
		foreach ($afields as $afield) {
			switch ($afield) {
		// purposefully ignore self::ALL, we already dealt with it
		case self::ALL: break;

		case self::COUNTRY:
			if (!$done[self::COUNTRY]) {
				list($results[self::COUNTRY_NAME], $results[self::COUNTRY_CODE]) = $this->readCountryNameAndCode($pointer);
				$done[self::COUNTRY] = true;
				$done[self::COUNTRY_CODE] = true;
				$done[self::COUNTRY_NAME] = true;
			}
			break;
		case self::COORDINATES:
			if (!$done[self::COORDINATES]) {
				list($results[self::LATITUDE], $results[self::LONGITUDE]) = $this->readLatitudeAndLongitude($pointer);
				$done[self::COORDINATES] = true;
				$done[self::LATITUDE] = true;
				$done[self::LONGITUDE] = true;
			}
			break;
		case self::IDD_AREA:
			if (!$done[self::IDD_AREA]) {
				list($results[self::IDD_CODE], $results[self::AREA_CODE]) = $this->readIddAndAreaCodes($pointer);
				$done[self::IDD_AREA] = true;
				$done[self::IDD_CODE] = true;
				$done[self::AREA_CODE] = true;
			}
			break;
		case self::WEATHER_STATION:
			if (!$done[self::WEATHER_STATION]) {
				list($results[self::WEATHER_STATION_NAME], $results[self::WEATHER_STATION_CODE]) = $this->readWeatherStationNameAndCode($pointer);
				$done[self::WEATHER_STATION] = true;
				$done[self::WEATHER_STATION_NAME] = true;
				$done[self::WEATHER_STATION_CODE] = true;
			}
			break;
		case self::MCC_MNC_MOBILE_CARRIER_NAME:
			if (!$done[self::MCC_MNC_MOBILE_CARRIER_NAME]) {
				list($results[self::MCC], $results[self::MNC], $results[self::MOBILE_CARRIER_NAME]) = $this->readMccMncAndMobileCarrierName($pointer);
				$done[self::MCC_MNC_MOBILE_CARRIER_NAME] = true;
				$done[self::MCC] = true;
				$done[self::MNC] = true;
				$done[self::MOBILE_CARRIER_NAME] = true;
			}
			break;

		case self::COUNTRY_CODE:
			if (!$done[self::COUNTRY_CODE]) {
				$results[self::COUNTRY_CODE] = $this->readCountryNameAndCode($pointer)[1];
				$done[self::COUNTRY_CODE] = true;
			}
			break;
		case self::COUNTRY_NAME:
			if (!$done[self::COUNTRY_NAME]) {
				$results[self::COUNTRY_NAME] = $this->readCountryNameAndCode($pointer)[0];
				$done[self::COUNTRY_NAME] = true;
			}
			break;
		case self::REGION_NAME:
			if (!$done[self::REGION_NAME]) {
				$results[self::REGION_NAME] = $this->readRegionName($pointer);
				$done[self::REGION_NAME] = true;
			}
			break;
		case self::CITY_NAME:
			if (!$done[self::CITY_NAME]) {
				$results[self::CITY_NAME] = $this->readCityName($pointer);
				$done[self::CITY_NAME] = true;
			}
			break;
		case self::LATITUDE:
			if (!$done[self::LATITUDE]) {
				$results[self::LATITUDE] = $this->readLatitudeAndLongitude($pointer)[0];
				$done[self::LATITUDE] = true;
			}
			break;
		case self::LONGITUDE:
			if (!$done[self::LONGITUDE]) {
				$results[self::LONGITUDE] = $this->readLatitudeAndLongitude($pointer)[1];
				$done[self::LONGITUDE] = true;
			}
			break;
		case self::ISP:
			if (!$done[self::ISP]) {
				$results[self::ISP] = $this->readIsp($pointer);
				$done[self::ISP] = true;
			}
			break;
		case self::DOMAIN_NAME:
			if (!$done[self::DOMAIN_NAME]) {
				$results[self::DOMAIN_NAME] = $this->readDomainName($pointer);
				$done[self::DOMAIN_NAME] = true;
			}
			break;
		case self::ZIP_CODE:
			if (!$done[self::ZIP_CODE]) {
				$results[self::ZIP_CODE] = $this->readZipCode($pointer);
				$done[self::ZIP_CODE] = true;
			}
			break;
		case self::TIME_ZONE:
			if (!$done[self::TIME_ZONE]) {
				$results[self::TIME_ZONE] = $this->readTimeZone($pointer);
				$done[self::TIME_ZONE] = true;
			}
			break;
		case self::NET_SPEED:
			if (!$done[self::NET_SPEED]) {
				$results[self::NET_SPEED] = $this->readNetSpeed($pointer);
				$done[self::NET_SPEED] = true;
			}
			break;
		case self::IDD_CODE:
			if (!$done[self::IDD_CODE]) {
				$results[self::IDD_CODE] = $this->readIddAndAreaCodes($pointer)[0];
				$done[self::IDD_CODE] = true;
			}
			break;
		case self::AREA_CODE:
			if (!$done[self::AREA_CODE]) {
				$results[self::AREA_CODE] = $this->readIddAndAreaCodes($pointer)[1];
				$done[self::AREA_CODE] = true;
			}
			break;
		case self::WEATHER_STATION_CODE:
			if (!$done[self::WEATHER_STATION_CODE]) {
				$results[self::WEATHER_STATION_CODE] = $this->readWeatherStationNameAndCode($pointer)[1];
				$done[self::WEATHER_STATION_CODE] = true;
			}
			break;
		case self::WEATHER_STATION_NAME:
			if (!$done[self::WEATHER_STATION_NAME]) {
				$results[self::WEATHER_STATION_NAME] = $this->readWeatherStationNameAndCode($pointer)[0];
				$done[self::WEATHER_STATION_NAME] = true;
			}
			break;
		case self::MCC:
			if (!$done[self::MCC]) {
				$results[self::MCC] = $this->readMccMncAndMobileCarrierName($pointer)[0];
				$done[self::MCC] = true;
			}
			break;
		case self::MNC:
			if (!$done[self::MNC]) {
				$results[self::MNC] = $this->readMccMncAndMobileCarrierName($pointer)[1];
				$done[self::MNC] = true;
			}
			break;
		case self::MOBILE_CARRIER_NAME:
			if (!$done[self::MOBILE_CARRIER_NAME]) {
				$results[self::MOBILE_CARRIER_NAME] = $this->readMccMncAndMobileCarrierName($pointer)[2];
				$done[self::MOBILE_CARRIER_NAME] = true;
			}
			break;
		case self::ELEVATION:
			if (!$done[self::ELEVATION]) {
				$results[self::ELEVATION] = $this->readElevation($pointer);
				$done[self::ELEVATION] = true;
			}
			break;
		case self::USAGE_TYPE:
			if (!$done[self::USAGE_TYPE]) {
				$results[self::USAGE_TYPE] = $this->readUsageType($pointer);
				$done[self::USAGE_TYPE] = true;
			}
			break;

		case self::IP_ADDRESS:
			if (!$done[self::IP_ADDRESS]) {
				$results[self::IP_ADDRESS] = $ip;
				$done[self::IP_ADDRESS] = true;
			}
			break;
		case self::IP_VERSION:
			if (!$done[self::IP_VERSION]) {
				$results[self::IP_VERSION] = $ipVersion;
				$done[self::IP_VERSION] = true;
			}
			break;
		case self::IP_NUMBER:
			if (!$done[self::IP_NUMBER]) {
				$results[self::IP_NUMBER] = $ipNumber;
				$done[self::IP_NUMBER] = true;
			}
			break;

		default:
			$results[$afield] = self::FIELD_NOT_KNOWN;
		}
		}

		// If we were asked for an array, or we have multiple results to return...
		if (\is_array($fields) || \count($results) > 1) {
			// return array
			if ($asNamed) {
				// apply translations if needed
				$return = [];
				foreach ($results as $key => $val) {
					if (\array_key_exists($key, static::$names)) {
						$return[static::$names[$key]] = $val;
					} else {
						$return[$key] = $val;
					}
				}

				return $return;
			}

			return $results;
		}
		// return a single value
		return array_values($results)[0];
	}