Skip to content

Commit

Permalink
Improvements to IP geolocation functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenreyes2000 committed Nov 12, 2024
1 parent 3200db3 commit 2ab73e3
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 127 deletions.
3 changes: 3 additions & 0 deletions functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
// Template router
require_once get_template_directory() . '/php/router.php';

// IP geolocation
require_once get_template_directory() . '/php/ip2geo.php';

// Outdated browser alert
require_once get_template_directory() . '/php/browsers.php';

Expand Down
2 changes: 1 addition & 1 deletion js/lib/lyquix/geolocate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export const geolocate = (() => {
async: true,
cache: false,
dataType: 'json',
url: cfg.tmplURL + '/php/ip2geo/',
url: cfg.siteURL + '/wp-json/lyquix/v3/ip2geo',
success: (data) => {
// Do not overwrite existing GPS location
if (vars.geolocate.location.source !== 'gps' && vars.geolocate.location.source !== 'gps-cookie') {
Expand Down
52 changes: 46 additions & 6 deletions php/customizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function customizer_add($wp_customize)
'width' => 1080,
'height' => 1080
],
'xl' =>[
'xl' => [
'width' => 1620,
'height' => 1080
]
Expand Down Expand Up @@ -174,6 +174,42 @@ function customizer_add($wp_customize)
'default' => '0'
],
],
'IP Geolocation' => [
'ip2geo_maxmind_license_key' => [
'type' => 'text',
'label' => 'MaxMind GeoLite2 License Key',
'default' => ''
],
'ip2geo_max_db_age' => [
'type' => 'text',
'label' => 'Maximum Database Age (days)',
'default' => '90'
],
'ip2geo_ip_address_header' => [
'type' => 'radio',
'label' => 'IP Address HTTP Header',
'choices' => [
'REMOTE_ADDR' => 'REMOTE_ADDR',
'HTTP_CF_CONNECTING_IP' => 'HTTP_CF_CONNECTING_IP',
'HTTP_CLIENT_IP' => 'HTTP_CLIENT_IP',
'HTTP_FASTLY_CLIENT_IP' => 'HTTP_FASTLY_CLIENT_IP',
'HTTP_FORWARDED' => 'HTTP_FORWARDED',
'HTTP_FORWARDED_FOR' => 'HTTP_FORWARDED_FOR',
'HTTP_TRUE_CLIENT_IP' => 'HTTP_TRUE_CLIENT_IP',
'HTTP_VIA' => 'HTTP_VIA',
'HTTP_X_CLUSTER_CLIENT_IP' => 'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_X_FORWARDED' => 'HTTP_X_FORWARDED',
'HTTP_X_FORWARDED_FOR' => 'HTTP_X_FORWARDED_FOR',
'HTTP_X_REAL_IP' => 'HTTP_X_REAL_IP'
],
'default' => 'REMOTE_ADDR'
],
'ip2geo_test_ip_address' => [
'type' => 'text',
'label' => 'Test IP Address',
'default' => ''
],
],
'Analytics' => [
'ga4_account' => [
'type' => 'text',
Expand Down Expand Up @@ -450,7 +486,9 @@ public function enqueue()

wp_register_script('lqx-customizer-checkbox-group-custom-control', false);
wp_enqueue_script('lqx-customizer-checkbox-group-custom-control');
wp_add_inline_script('lqx-customizer-checkbox-group-custom-control', '
wp_add_inline_script(
'lqx-customizer-checkbox-group-custom-control',
'
jQuery(document).ready(function() {
jQuery(\'#customize-theme-controls\').on(\'change\', \'.customize-control-checkbox-group input[type="checkbox"]\', function() {
let values = jQuery(this).parents(\'.customize-control-checkbox-group\').find(\'input[type="checkbox"]:checked\').map(
Expand Down Expand Up @@ -484,7 +522,7 @@ public function render_content()
<?php endforeach; ?>
</div>
<input type="hidden" <?php $this->link(); ?> value="<?= esc_attr(json_encode($values)); ?>" />
<?php
<?php
}
}

Expand All @@ -499,7 +537,9 @@ public function enqueue()

wp_register_script('lqx-customizer-viewports-custom-control', false);
wp_enqueue_script('lqx-customizer-viewports-custom-control');
wp_add_inline_script('lqx-customizer-viewports-custom-control', '
wp_add_inline_script(
'lqx-customizer-viewports-custom-control',
'
jQuery(document).ready(function() {
jQuery(\'#customize-theme-controls\').on(\'input change\', \'.customize-control-viewports input[type="number"]\', function() {
var values = {};
Expand Down Expand Up @@ -550,12 +590,12 @@ public function render_content()
'width' => 1080,
'height' => 1080
],
'xl' =>[
'xl' => [
'width' => 1620,
'height' => 1080
]
];
?>
?>
<div class="customize-control-viewports">
<?php foreach ($values as $label => $viewport) : ?>
<label>
Expand Down
118 changes: 118 additions & 0 deletions php/ip2geo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

/**
* ip2geo.php - Lyquix IP geolocation
*
* @version 3.1.0
* @package wp_theme_lyquix
* @author Lyquix
* @copyright Copyright (C) 2015 - 2024 Lyquix
* @license GNU General Public License version 2 or later
* @link https://github.com/Lyquix/wp_theme_lyquix
*/

// .d8888b. 88888888888 .d88888b. 8888888b. 888
// d88P Y88b 888 d88P" "Y88b 888 Y88b 888
// Y88b. 888 888 888 888 888 888
// "Y888b. 888 888 888 888 d88P 888
// "Y88b. 888 888 888 8888888P" 888
// "888 888 888 888 888 Y8P
// Y88b d88P 888 Y88b. .d88P 888 "
// "Y8888P" 888 "Y88888P" 888 888
//
// DO NOT MODIFY THIS FILE!

namespace lqx\ip2geo;

function rest_route()
{

$db_filename = 'GeoLite2-City';
$db_basepath = wp_get_upload_dir()['basedir'] . '/' . $db_filename;
$db_tar_gz = $db_basepath . '.tar.gz';
$db_tar = $db_basepath . '.tar';
$db = $db_basepath . '.mmdb';
$db_exists = file_exists($db);

// If database doesn't exist, attempt to download and extract it
if (!$db_exists || ($db_exists && (time() - filemtime($db) > get_theme_mod('ip2geo_max_db_age', '90') * 86400))) {
$download_url = 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=' . get_theme_mod('ip2geo_maxmind_license_key', '') . '&suffix=tar.gz';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $download_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$download_content = curl_exec($ch);
$curl_info = curl_getinfo($ch);
$curl_err = curl_errno($ch);

// Check if the response code is 200
if ($curl_info['http_code'] !== 200 || $curl_err !== 0) return ['error' => 'Error downloading database', 'curl_info' => $curl_info, 'curl_err' => curl_error($ch)];
curl_close($ch);

$fh = fopen($db_tar_gz, 'w');
fwrite($fh, $download_content);
fclose($fh);

// Decompress gz
$p = new \PharData($db_tar_gz);
$p->decompress();
unlink($db_tar_gz);

// Unarchive tar
$p = new \PharData($db_tar);
$p->extractTo(wp_get_upload_dir()['basedir']);
unlink($db_tar);

// Move file, and delete directory
$extract_dir = glob(wp_get_upload_dir()['basedir'] . '/' . $db_filename . '*', GLOB_ONLYDIR)[0];
rename($extract_dir . '/' . $db_filename . '.mmdb', $db);
foreach (glob($extract_dir . '/*') as $file) unlink($file);
rmdir($extract_dir);
}

// Get IP address from HTTP request
$ip = get_theme_mod('ip2geo_test_ip_address', '') ?: $_SERVER[get_theme_mod('ip2geo_ip_address_header', 'REMOTE_ADDR')];

// Sanitize IP address
$ip = filter_var($ip, FILTER_VALIDATE_IP);

// Catch if IP address is invalid
if (!$ip) return ['error' => 'Invalid IP address'];

// Check if IP address is private
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) return ['error' => 'Private IP address'];

// Include required classes
require_once 'ip2geo/Reader.php';
require_once 'ip2geo/Decoder.php';
require_once 'ip2geo/InvalidDatabaseException.php';
require_once 'ip2geo/Metadata.php';
require_once 'ip2geo/Util.php';

// Get location data
$reader = new Reader($db);
$geo = $reader->get($ip);
$reader->close();

return [
'city' => $geo['city']['names']['en'],
'subdivision' => $geo['subdivisions'][0]['names']['en'],
'country' => $geo['country']['iso_code'],
'continent' => $geo['continent']['code'],
'time_zone' => $geo['location']['time_zone'],
'lat' => $geo['location']['latitude'],
'lon' => $geo['location']['longitude'],
'radius' => $geo['location']['accuracy_radius'], // in km
'ip' => $ip
];
}

// Register a REST API endpoint to get the alerts from site options
add_action('rest_api_init', function () {
register_rest_route('lyquix/v3', '/ip2geo', [
'methods' => 'GET',
'callback' => '\lqx\ip2geo\rest_route',
'permission_callback' => '__return_true',
]);
});
3 changes: 3 additions & 0 deletions php/ip2geo/Decoder.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?php

namespace lqx\ip2geo;

class Decoder
{
private $fileStream;
Expand Down
3 changes: 3 additions & 0 deletions php/ip2geo/InvalidDatabaseException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?php

namespace lqx\ip2geo;

/**
* This class should be thrown when unexpected data is found in the database.
*/
Expand Down
2 changes: 2 additions & 0 deletions php/ip2geo/Metadata.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php

namespace lqx\ip2geo;
/**
* This class provides the metadata for the MaxMind DB file.
*
Expand Down
3 changes: 3 additions & 0 deletions php/ip2geo/Reader.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?php

namespace lqx\ip2geo;

/**
* Instances of this class provide a reader for the MaxMind DB format. IP
* addresses can be looked up using the <code>get</code> method.
Expand Down
3 changes: 3 additions & 0 deletions php/ip2geo/Util.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?php

namespace lqx\ip2geo;

class Util
{
// Read a given number of bytes from a stream
Expand Down
16 changes: 0 additions & 16 deletions php/ip2geo/config.dist.php

This file was deleted.

104 changes: 0 additions & 104 deletions php/ip2geo/index.php

This file was deleted.

0 comments on commit 2ab73e3

Please sign in to comment.