-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Version bump, PHP version requirement upped
Mostly small updates to documentation. New helper functions were added to improve the getIpAddress function.
- Loading branch information
1 parent
ffff535
commit fc0488b
Showing
2 changed files
with
104 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ Usage is fairly simple once installed. Simply add the following code to the page | |
|
||
### Requirements | ||
|
||
- Simple Counter works with PHP 7.0.0 or above. | ||
- Simple Counter works with PHP 8.0.0 or above. | ||
|
||
### Submitting bugs and feature requests | ||
|
||
|
@@ -81,7 +81,7 @@ branches for both of these features and send two requests. | |
|
||
### Author | ||
|
||
Eric Sizemore - <[email protected]> - <http://www.secondversion.com> | ||
Eric Sizemore - <[email protected]> - <https://www.secondversion.com> | ||
|
||
### License | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,66 @@ | ||
<?php | ||
|
||
/** | ||
* @author Eric Sizemore <[email protected]> | ||
* @package SV's Simple Counter | ||
* @link http://www.secondversion.com/downloads/ | ||
* @version 4.0.3 | ||
* @copyright (C) 2006 - 2021 Eric Sizemore | ||
* @license GNU Lesser General Public License | ||
* | ||
* SV's Simple Counter is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
* SV's Simple Counter - A simple web hit counter. | ||
* | ||
* @author Eric Sizemore <[email protected]> | ||
* @package SV's Simple Counter | ||
* @link https://www.secondversion.com/ | ||
* @version 4.0.4 | ||
* @copyright (C) 2006 - 2023 Eric Sizemore | ||
* @license GNU Lesser General Public License | ||
*/ | ||
namespace Esi\SimpleCounter; | ||
|
||
use Exception; | ||
|
||
/** | ||
* Main class that processes the counter. | ||
* SV's Simple Counter - A simple web hit counter. | ||
* | ||
* @author Eric Sizemore <[email protected]> | ||
* @package SV's Simple Counter | ||
* @link https://www.secondversion.com/ | ||
* @version 4.0.4 | ||
* @copyright (C) 2006 - 2023 Eric Sizemore | ||
* @license GNU Lesser General Public License | ||
* | ||
* Copyright (C) 2006 - 2023 Eric Sizemore. All rights reserved. | ||
* | ||
* SV's Simple Counter is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
class Counter | ||
{ | ||
/** User Configuration **/ | ||
|
||
// Log file locations/paths. | ||
const COUNT_FILE = 'counter/logs/counter.txt'; | ||
const IP_FILE = 'counter/logs/ips.txt'; | ||
private const COUNT_FILE = 'counter/logs/counter.txt'; | ||
private const IP_FILE = 'counter/logs/ips.txt'; | ||
|
||
// Use file locking? | ||
const USE_FLOCK = true; | ||
private const USE_FLOCK = true; | ||
|
||
// Count only unique visitors? | ||
const ONLY_UNIQUE = true; | ||
private const ONLY_UNIQUE = true; | ||
|
||
// Show count as images? | ||
const USE_IMAGES = false; | ||
private const USE_IMAGES = false; | ||
|
||
// Path to the images. | ||
const IMAGE_DIR = 'counter/images/'; | ||
private const IMAGE_DIR = 'counter/images/'; | ||
|
||
// Image extension. | ||
const IMAGE_EXT = '.gif'; | ||
private const IMAGE_EXT = '.gif'; | ||
|
||
/** End User Configuration **/ | ||
|
||
|
@@ -88,9 +101,10 @@ public static function getInstance(): self | |
*/ | ||
private function getIpAddress(bool $trustProxyHeaders = false): string | ||
{ | ||
// Pretty self-explanatory. Try to get an 'accurate' IP | ||
$ip = $_SERVER['REMOTE_ADDR']; | ||
|
||
if ($trustProxyHeaders === false) { | ||
if ($trustProxyHeaders) { | ||
return $ip; | ||
} | ||
|
||
|
@@ -106,49 +120,97 @@ private function getIpAddress(bool $trustProxyHeaders = false): string | |
|
||
if (!empty($ips)) { | ||
foreach ($ips AS $val) { | ||
if ( | ||
\inet_ntop(\inet_pton($val)) == $val | ||
AND !\preg_match("#^(10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.|fe80:|fe[c-f][0-f]:|f[c-d][0-f]{2}:)#i", $val) | ||
) { | ||
if (\inet_ntop(\inet_pton($val)) == $val AND self::isPublicIp($val)) { | ||
$ip = $val; | ||
break; | ||
} | ||
} | ||
} | ||
unset($ips); | ||
|
||
if (!$ip AND isset($_SERVER['HTTP_CLIENT_IP'])) { | ||
$ip = $_SERVER['HTTP_CLIENT_IP']; | ||
} | ||
return $ip; | ||
} | ||
|
||
// --- getIpAddress helpers --- // | ||
/** | ||
* isPrivateIp() | ||
* | ||
* Determines if an IP address is within the private range. | ||
* | ||
* @param string $ipaddress IP address to check. | ||
* @return bool | ||
*/ | ||
private function isPrivateIp(string $ipaddress): bool | ||
{ | ||
return !(bool)\filter_var( | ||
$ipaddress, | ||
\FILTER_VALIDATE_IP, | ||
\FILTER_FLAG_IPV4 | \FILTER_FLAG_IPV6 | \FILTER_FLAG_NO_PRIV_RANGE | ||
); | ||
} | ||
|
||
/** | ||
* isReservedIp() | ||
* | ||
* Determines if an IP address is within the reserved range. | ||
* | ||
* @param string $ipaddress IP address to check. | ||
* @return bool | ||
*/ | ||
private function isReservedIp(string $ipaddress): bool | ||
{ | ||
return !(bool)\filter_var( | ||
$ipaddress, | ||
\FILTER_VALIDATE_IP, | ||
\FILTER_FLAG_IPV4 | \FILTER_FLAG_IPV6 | \FILTER_FLAG_NO_RES_RANGE | ||
); | ||
} | ||
|
||
/** | ||
* isPublicIp() | ||
* | ||
* Determines if an IP address is not within the private or reserved ranges. | ||
* | ||
* @param string $ipaddress IP address to check. | ||
* @return bool | ||
*/ | ||
private function isPublicIp(string $ipaddress): bool | ||
{ | ||
return (bool)(!self::isPrivateIp($ipaddress) AND !self::isReservedIp($ipaddress)); | ||
} | ||
|
||
/** | ||
* We use this function to open and read/write to files. | ||
* | ||
* @param string $file Filename | ||
* @param string $mode Mode (r, w, a, etc..) | ||
* @param string $data If writing to the file, the data to write | ||
* @return mixed | ||
* | ||
* @throws Exception | ||
*/ | ||
private function readWriteFile(string $file, string $mode, string $data = '') | ||
private function readWriteFile(string $file, string $mode, string $data = ''): mixed | ||
{ | ||
if (!\file_exists($file) OR !\is_writable($file)) { | ||
throw new \Exception(\sprintf("'%s' does not exist or is not writable.", $file)); | ||
throw new Exception(\sprintf("'%s' does not exist or is not writable.", $file)); | ||
} | ||
|
||
if (!($fp = \fopen($file, $mode))) { | ||
throw new \Exception(\sprintf("'%s' could not be opened.", $file)); | ||
throw new Exception(\sprintf("'%s' could not be opened.", $file)); | ||
} | ||
|
||
$return = null; | ||
|
||
if (self::USE_FLOCK AND \flock($fp, LOCK_EX)) { | ||
if (self::USE_FLOCK AND \flock($fp, \LOCK_EX)) { | ||
if ($mode == 'r') { | ||
$return = \fread($fp, \filesize($file)); | ||
} else { | ||
\fwrite($fp, $data); | ||
} | ||
\flock($fp, LOCK_UN); | ||
\flock($fp, \LOCK_UN); | ||
} else { | ||
if ($mode == 'r') { | ||
$return = \fread($fp, \filesize($file)); | ||
|
@@ -176,7 +238,7 @@ public function process() | |
$ip = self::getIpAddress(); | ||
|
||
$ips = \trim(self::readWriteFile(self::IP_FILE, 'r')); | ||
$ips = \preg_split("#\n#", $ips, -1, PREG_SPLIT_NO_EMPTY); | ||
$ips = \preg_split("#\n#", $ips, -1, \PREG_SPLIT_NO_EMPTY); | ||
|
||
// They've not visited before | ||
if (!\in_array($ip, $ips)) { | ||
|
@@ -191,7 +253,7 @@ public function process() | |
|
||
// Do we want to display the # visitors as graphics? | ||
if (self::USE_IMAGES) { | ||
$count = \preg_split('##', $count, -1, PREG_SPLIT_NO_EMPTY); | ||
$count = \preg_split('##', $count, -1, \PREG_SPLIT_NO_EMPTY); | ||
$length = \count($count); | ||
|
||
for ($i = 0; $i < $length; $i++) { | ||
|