: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
namespace Wordfence\MmdbReader\Io;
use Wordfence\MmdbReader\Exception\IoException;
const POSITION_START = 0;
const DIRECTION_FORWARD = 1;
const DIRECTION_REVERSE = -1;
const CHUNK_SIZE_DEFAULT = 1024;
public function __construct($resource, $close = true) {
$this->resource = $resource;
public function __destruct() {
public function seek($offset, $whence = SEEK_SET) {
if (fseek($this->resource, $offset, $whence) !== 0)
throw new IoException("Seeking file to offset {$offset} failed");
public function getPosition() {
$position = ftell($this->resource);
throw new IoException('Retrieving current position in file failed');
public function isAtStart() {
return $this->getPosition() === self::POSITION_START;
public function isAtEnd() {
return feof($this->resource);
public function read($length) {
$read = fread($this->resource, $length);
throw new IoException("Reading {$length} byte(s) from file failed");
public function readByte() {
return ord($this->read(1));
public function readAll($chunkSize = self::CHUNK_SIZE_DEFAULT) {
$chunk = $this->read($chunkSize);
public function locateString($string, $direction, $limit = null, $after = false) {
$searchStart = $limit === null ? null : $this->getPosition();
$length = strlen($string);
$position = $searchStart;
if ($direction === self::DIRECTION_REVERSE)
$this->seek($position, SEEK_SET);
//This assumes that a seek failure means that the target position is out of range (and hence the search just needs to stop rather than throwing an exception)
$test = $this->read($length);
return $position + ($after ? $length : 0);
} while ($limit === null || abs($position - $searchStart) < $limit);