File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/Core.tar
BLAKE2b.php 0000644 00000000142 15153624057 0006324 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class BLAKE2b extends \ParagonIE_Sodium_Core_BLAKE2b
{
}
Base64/Common.php 0000644 00000015027 15153624057 0007546 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core_Base64
*
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* We have to copy/paste the contents into the variant files because PHP 5.2
* doesn't support late static binding, and we have no better workaround
* available that won't break PHP 7+. Therefore, we're forced to duplicate code.
*/
abstract class ParagonIE_Sodium_Core_Base64_Common
{
/**
* Encode into Base64
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws TypeError
*/
public static function encode($src)
{
return self::doEncode($src, true);
}
/**
* Encode into Base64, no = padding
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws TypeError
*/
public static function encodeUnpadded($src)
{
return self::doEncode($src, false);
}
/**
* @param string $src
* @param bool $pad Include = padding?
* @return string
* @throws TypeError
*/
protected static function doEncode($src, $pad = true)
{
$dest = '';
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
// Main loop (no padding):
for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
$b0 = $chunk[1];
$b1 = $chunk[2];
$b2 = $chunk[3];
$dest .=
self::encode6Bits( $b0 >> 2 ) .
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
self::encode6Bits( $b2 & 63);
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
$b0 = $chunk[1];
if ($i + 1 < $srcLen) {
$b1 = $chunk[2];
$dest .=
self::encode6Bits($b0 >> 2) .
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
self::encode6Bits(($b1 << 2) & 63);
if ($pad) {
$dest .= '=';
}
} else {
$dest .=
self::encode6Bits( $b0 >> 2) .
self::encode6Bits(($b0 << 4) & 63);
if ($pad) {
$dest .= '==';
}
}
}
return $dest;
}
/**
* decode from base64 into binary
*
* Base64 character set "./[A-Z][a-z][0-9]"
*
* @param string $src
* @param bool $strictPadding
* @return string
* @throws RangeException
* @throws TypeError
* @psalm-suppress RedundantCondition
*/
public static function decode($src, $strictPadding = false)
{
// Remove padding
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
if ($srcLen === 0) {
return '';
}
if ($strictPadding) {
if (($srcLen & 3) === 0) {
if ($src[$srcLen - 1] === '=') {
$srcLen--;
if ($src[$srcLen - 1] === '=') {
$srcLen--;
}
}
}
if (($srcLen & 3) === 1) {
throw new RangeException(
'Incorrect padding'
);
}
if ($src[$srcLen - 1] === '=') {
throw new RangeException(
'Incorrect padding'
);
}
} else {
$src = rtrim($src, '=');
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
}
$err = 0;
$dest = '';
// Main loop (no padding):
for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
$c0 = self::decode6Bits($chunk[1]);
$c1 = self::decode6Bits($chunk[2]);
$c2 = self::decode6Bits($chunk[3]);
$c3 = self::decode6Bits($chunk[4]);
$dest .= pack(
'CCC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff),
((($c2 << 6) | $c3 ) & 0xff)
);
$err |= ($c0 | $c1 | $c2 | $c3) >> 8;
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
$c0 = self::decode6Bits($chunk[1]);
if ($i + 2 < $srcLen) {
$c1 = self::decode6Bits($chunk[2]);
$c2 = self::decode6Bits($chunk[3]);
$dest .= pack(
'CC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff)
);
$err |= ($c0 | $c1 | $c2) >> 8;
} elseif ($i + 1 < $srcLen) {
$c1 = self::decode6Bits($chunk[2]);
$dest .= pack(
'C',
((($c0 << 2) | ($c1 >> 4)) & 0xff)
);
$err |= ($c0 | $c1) >> 8;
} elseif ($i < $srcLen && $strictPadding) {
$err |= 1;
}
}
/** @var bool $check */
$check = ($err === 0);
if (!$check) {
throw new RangeException(
'Base64::decode() only expects characters in the correct base64 alphabet'
);
}
return $dest;
}
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* [A-Z] [a-z] [0-9] + /
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
*
* @param int $src
* @return int
*/
abstract protected static function decode6Bits($src);
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
abstract protected static function encode6Bits($src);
}
Base64/Original.php 0000644 00000017055 15153624057 0010065 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core_Base64
*
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*/
class ParagonIE_Sodium_Core_Base64_Original
{
// COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
/**
* Encode into Base64
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws TypeError
*/
public static function encode($src)
{
return self::doEncode($src, true);
}
/**
* Encode into Base64, no = padding
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws TypeError
*/
public static function encodeUnpadded($src)
{
return self::doEncode($src, false);
}
/**
* @param string $src
* @param bool $pad Include = padding?
* @return string
* @throws TypeError
*/
protected static function doEncode($src, $pad = true)
{
$dest = '';
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
// Main loop (no padding):
for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
$b0 = $chunk[1];
$b1 = $chunk[2];
$b2 = $chunk[3];
$dest .=
self::encode6Bits( $b0 >> 2 ) .
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
self::encode6Bits( $b2 & 63);
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
$b0 = $chunk[1];
if ($i + 1 < $srcLen) {
$b1 = $chunk[2];
$dest .=
self::encode6Bits($b0 >> 2) .
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
self::encode6Bits(($b1 << 2) & 63);
if ($pad) {
$dest .= '=';
}
} else {
$dest .=
self::encode6Bits( $b0 >> 2) .
self::encode6Bits(($b0 << 4) & 63);
if ($pad) {
$dest .= '==';
}
}
}
return $dest;
}
/**
* decode from base64 into binary
*
* Base64 character set "./[A-Z][a-z][0-9]"
*
* @param string $src
* @param bool $strictPadding
* @return string
* @throws RangeException
* @throws TypeError
* @psalm-suppress RedundantCondition
*/
public static function decode($src, $strictPadding = false)
{
// Remove padding
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
if ($srcLen === 0) {
return '';
}
if ($strictPadding) {
if (($srcLen & 3) === 0) {
if ($src[$srcLen - 1] === '=') {
$srcLen--;
if ($src[$srcLen - 1] === '=') {
$srcLen--;
}
}
}
if (($srcLen & 3) === 1) {
throw new RangeException(
'Incorrect padding'
);
}
if ($src[$srcLen - 1] === '=') {
throw new RangeException(
'Incorrect padding'
);
}
} else {
$src = rtrim($src, '=');
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
}
$err = 0;
$dest = '';
// Main loop (no padding):
for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
$c0 = self::decode6Bits($chunk[1]);
$c1 = self::decode6Bits($chunk[2]);
$c2 = self::decode6Bits($chunk[3]);
$c3 = self::decode6Bits($chunk[4]);
$dest .= pack(
'CCC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff),
((($c2 << 6) | $c3) & 0xff)
);
$err |= ($c0 | $c1 | $c2 | $c3) >> 8;
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
$c0 = self::decode6Bits($chunk[1]);
if ($i + 2 < $srcLen) {
$c1 = self::decode6Bits($chunk[2]);
$c2 = self::decode6Bits($chunk[3]);
$dest .= pack(
'CC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff)
);
$err |= ($c0 | $c1 | $c2) >> 8;
} elseif ($i + 1 < $srcLen) {
$c1 = self::decode6Bits($chunk[2]);
$dest .= pack(
'C',
((($c0 << 2) | ($c1 >> 4)) & 0xff)
);
$err |= ($c0 | $c1) >> 8;
} elseif ($i < $srcLen && $strictPadding) {
$err |= 1;
}
}
/** @var bool $check */
$check = ($err === 0);
if (!$check) {
throw new RangeException(
'Base64::decode() only expects characters in the correct base64 alphabet'
);
}
return $dest;
}
// COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* [A-Z] [a-z] [0-9] + /
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
*
* @param int $src
* @return int
*/
protected static function decode6Bits($src)
{
$ret = -1;
// if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
// if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
// if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
// if ($src == 0x2b) $ret += 62 + 1;
$ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
// if ($src == 0x2f) ret += 63 + 1;
$ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode6Bits($src)
{
$diff = 0x41;
// if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
$diff += ((25 - $src) >> 8) & 6;
// if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
$diff -= ((51 - $src) >> 8) & 75;
// if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
$diff -= ((61 - $src) >> 8) & 15;
// if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
$diff += ((62 - $src) >> 8) & 3;
return pack('C', $src + $diff);
}
}
Base64/UrlSafe.php 0000644 00000017063 15153624057 0007661 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core_Base64UrlSafe
*
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*/
class ParagonIE_Sodium_Core_Base64_UrlSafe
{
// COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
/**
* Encode into Base64
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws TypeError
*/
public static function encode($src)
{
return self::doEncode($src, true);
}
/**
* Encode into Base64, no = padding
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws TypeError
*/
public static function encodeUnpadded($src)
{
return self::doEncode($src, false);
}
/**
* @param string $src
* @param bool $pad Include = padding?
* @return string
* @throws TypeError
*/
protected static function doEncode($src, $pad = true)
{
$dest = '';
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
// Main loop (no padding):
for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
$b0 = $chunk[1];
$b1 = $chunk[2];
$b2 = $chunk[3];
$dest .=
self::encode6Bits( $b0 >> 2 ) .
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
self::encode6Bits( $b2 & 63);
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
$b0 = $chunk[1];
if ($i + 1 < $srcLen) {
$b1 = $chunk[2];
$dest .=
self::encode6Bits($b0 >> 2) .
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
self::encode6Bits(($b1 << 2) & 63);
if ($pad) {
$dest .= '=';
}
} else {
$dest .=
self::encode6Bits( $b0 >> 2) .
self::encode6Bits(($b0 << 4) & 63);
if ($pad) {
$dest .= '==';
}
}
}
return $dest;
}
/**
* decode from base64 into binary
*
* Base64 character set "./[A-Z][a-z][0-9]"
*
* @param string $src
* @param bool $strictPadding
* @return string
* @throws RangeException
* @throws TypeError
* @psalm-suppress RedundantCondition
*/
public static function decode($src, $strictPadding = false)
{
// Remove padding
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
if ($srcLen === 0) {
return '';
}
if ($strictPadding) {
if (($srcLen & 3) === 0) {
if ($src[$srcLen - 1] === '=') {
$srcLen--;
if ($src[$srcLen - 1] === '=') {
$srcLen--;
}
}
}
if (($srcLen & 3) === 1) {
throw new RangeException(
'Incorrect padding'
);
}
if ($src[$srcLen - 1] === '=') {
throw new RangeException(
'Incorrect padding'
);
}
} else {
$src = rtrim($src, '=');
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
}
$err = 0;
$dest = '';
// Main loop (no padding):
for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
$c0 = self::decode6Bits($chunk[1]);
$c1 = self::decode6Bits($chunk[2]);
$c2 = self::decode6Bits($chunk[3]);
$c3 = self::decode6Bits($chunk[4]);
$dest .= pack(
'CCC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff),
((($c2 << 6) | $c3) & 0xff)
);
$err |= ($c0 | $c1 | $c2 | $c3) >> 8;
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
$c0 = self::decode6Bits($chunk[1]);
if ($i + 2 < $srcLen) {
$c1 = self::decode6Bits($chunk[2]);
$c2 = self::decode6Bits($chunk[3]);
$dest .= pack(
'CC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff)
);
$err |= ($c0 | $c1 | $c2) >> 8;
} elseif ($i + 1 < $srcLen) {
$c1 = self::decode6Bits($chunk[2]);
$dest .= pack(
'C',
((($c0 << 2) | ($c1 >> 4)) & 0xff)
);
$err |= ($c0 | $c1) >> 8;
} elseif ($i < $srcLen && $strictPadding) {
$err |= 1;
}
}
/** @var bool $check */
$check = ($err === 0);
if (!$check) {
throw new RangeException(
'Base64::decode() only expects characters in the correct base64 alphabet'
);
}
return $dest;
}
// COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* [A-Z] [a-z] [0-9] + /
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
*
* @param int $src
* @return int
*/
protected static function decode6Bits($src)
{
$ret = -1;
// if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
// if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
// if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
// if ($src == 0x2c) $ret += 62 + 1;
$ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;
// if ($src == 0x5f) ret += 63 + 1;
$ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode6Bits($src)
{
$diff = 0x41;
// if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
$diff += ((25 - $src) >> 8) & 6;
// if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
$diff -= ((51 - $src) >> 8) & 75;
// if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
$diff -= ((61 - $src) >> 8) & 13;
// if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
$diff += ((62 - $src) >> 8) & 49;
return pack('C', $src + $diff);
}
}
ChaCha20/Ctx.php 0000644 00000000154 15153624057 0007274 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\ChaCha20;
class Ctx extends \ParagonIE_Sodium_Core_ChaCha20_Ctx
{
}
ChaCha20/IetfCtx.php 0000644 00000000164 15153624057 0010105 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\ChaCha20;
class IetfCtx extends \ParagonIE_Sodium_Core_ChaCha20_IetfCtx
{
}
ChaCha20.php 0000644 00000000144 15153624057 0006535 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class ChaCha20 extends \ParagonIE_Sodium_Core_ChaCha20
{
}
Curve25519/Fe.php 0000644 00000000156 15153624057 0007313 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519;
class Fe extends \ParagonIE_Sodium_Core_Curve25519_Fe
{
}
Curve25519/Ge/Cached.php 0000644 00000000174 15153624057 0010463 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
class Cached extends \ParagonIE_Sodium_Core_Curve25519_Ge_Cached
{
}
Curve25519/Ge/P1p1.php 0000644 00000000170 15153624057 0010031 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
class P1p1 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
{
}
Curve25519/Ge/P2.php 0000644 00000000164 15153624057 0007574 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
class P2 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P2
{
}
Curve25519/Ge/P3.php 0000644 00000000164 15153624057 0007575 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
class P3 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P3
{
}
Curve25519/Ge/Precomp.php 0000644 00000000176 15153624057 0010723 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
class Precomp extends \ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
{
}
Curve25519/H.php 0000644 00000000154 15153624057 0007146 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Curve25519;
class H extends \ParagonIE_Sodium_Core_Curve25519_H
{
}
Curve25519/README.md 0000644 00000000332 15153624057 0007523 0 ustar 00 # Curve25519 Data Structures
These are PHP implementation of the [structs used in the ref10 curve25519 code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h).
Curve25519.php 0000644 00000000150 15153624057 0006753 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class Curve25519 extends \ParagonIE_Sodium_Core_Curve25519
{
}
Ed25519.php 0000644 00000000142 15153624057 0006220 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class Ed25519 extends \ParagonIE_Sodium_Core_Ed25519
{
}
HChaCha20.php 0000644 00000000146 15153624057 0006647 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class HChaCha20 extends \ParagonIE_Sodium_Core_HChaCha20
{
}
HSalsa20.php 0000644 00000000144 15153624057 0006601 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class HSalsa20 extends \ParagonIE_Sodium_Core_HSalsa20
{
}
Poly1305/State.php 0000644 00000000160 15153624057 0007576 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core\Poly1305;
class State extends \ParagonIE_Sodium_Core_Poly1305_State
{
}
Poly1305.php 0000644 00000000144 15153624057 0006520 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class Poly1305 extends \ParagonIE_Sodium_Core_Poly1305
{
}
Ristretto255.php 0000644 00000052574 15153624057 0007535 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core_Ristretto255
*/
class ParagonIE_Sodium_Core_Ristretto255 extends ParagonIE_Sodium_Core_Ed25519
{
const crypto_core_ristretto255_HASHBYTES = 64;
const HASH_SC_L = 48;
const CORE_H2C_SHA256 = 1;
const CORE_H2C_SHA512 = 2;
/**
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @param int $b
* @return ParagonIE_Sodium_Core_Curve25519_Fe
*/
public static function fe_cneg(ParagonIE_Sodium_Core_Curve25519_Fe $f, $b)
{
$negf = self::fe_neg($f);
return self::fe_cmov($f, $negf, $b);
}
/**
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core_Curve25519_Fe
* @throws SodiumException
*/
public static function fe_abs(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
return self::fe_cneg($f, self::fe_isnegative($f));
}
/**
* Returns 0 if this field element results in all NUL bytes.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
* @return int
* @throws SodiumException
*/
public static function fe_iszero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
{
static $zero;
if ($zero === null) {
$zero = str_repeat("\x00", 32);
}
/** @var string $zero */
$str = self::fe_tobytes($f);
$d = 0;
for ($i = 0; $i < 32; ++$i) {
$d |= self::chrToInt($str[$i]);
}
return (($d - 1) >> 31) & 1;
}
/**
* @param ParagonIE_Sodium_Core_Curve25519_Fe $u
* @param ParagonIE_Sodium_Core_Curve25519_Fe $v
* @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int}
*
* @throws SodiumException
*/
public static function ristretto255_sqrt_ratio_m1(
ParagonIE_Sodium_Core_Curve25519_Fe $u,
ParagonIE_Sodium_Core_Curve25519_Fe $v
) {
$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
$v3 = self::fe_mul(
self::fe_sq($v),
$v
); /* v3 = v^3 */
$x = self::fe_mul(
self::fe_mul(
self::fe_sq($v3),
$u
),
$v
); /* x = uv^7 */
$x = self::fe_mul(
self::fe_mul(
self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */
$v3
),
$u
); /* x = uv^3(uv^7)^((q-5)/8) */
$vxx = self::fe_mul(
self::fe_sq($x),
$v
); /* vx^2 */
$m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */
$p_root_check = self::fe_add($vxx, $u); /* vx^2+u */
$f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */
$f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */
$has_m_root = self::fe_iszero($m_root_check);
$has_p_root = self::fe_iszero($p_root_check);
$has_f_root = self::fe_iszero($f_root_check);
$x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */
$x = self::fe_abs(
self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root)
);
return array(
'x' => $x,
'nonsquare' => $has_m_root | $has_p_root
);
}
/**
* @param string $s
* @return int
* @throws SodiumException
*/
public static function ristretto255_point_is_canonical($s)
{
$c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f;
for ($i = 30; $i > 0; --$i) {
$c |= self::chrToInt($s[$i]) ^ 0xff;
}
$c = ($c - 1) >> 8;
$d = (0xed - 1 - self::chrToInt($s[0])) >> 8;
$e = self::chrToInt($s[31]) >> 7;
return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1);
}
/**
* @param string $s
* @param bool $skipCanonicalCheck
* @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int}
* @throws SodiumException
*/
public static function ristretto255_frombytes($s, $skipCanonicalCheck = false)
{
if (!$skipCanonicalCheck) {
if (!self::ristretto255_point_is_canonical($s)) {
throw new SodiumException('S is not canonical');
}
}
$s_ = self::fe_frombytes($s);
$ss = self::fe_sq($s_); /* ss = s^2 */
$u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */
$u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */
$u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */
$u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */
$v = self::fe_mul(
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d),
$u1u1
); /* v = d*u1^2 */
$v = self::fe_neg($v); /* v = -d*u1^2 */
$v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */
$v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */
// fe25519_1(one);
// notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
$one = self::fe_1();
$result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2);
$inv_sqrt = $result['x'];
$notsquare = $result['nonsquare'];
$h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
$h->X = self::fe_mul($inv_sqrt, $u2);
$h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v);
$h->X = self::fe_mul($h->X, $s_);
$h->X = self::fe_abs(
self::fe_add($h->X, $h->X)
);
$h->Y = self::fe_mul($u1, $h->Y);
$h->Z = self::fe_1();
$h->T = self::fe_mul($h->X, $h->Y);
$res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y));
return array('h' => $h, 'res' => $res);
}
/**
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
* @return string
* @throws SodiumException
*/
public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
{
$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
$invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd);
$u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */
$zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */
$u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */
$u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */
$u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */
$one = self::fe_1();
// fe25519_1(one);
// (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
$result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2);
$inv_sqrt = $result['x'];
$den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */
$den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */
$z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */
$ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */
$iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */
$eden = self::fe_mul($den1, $invsqrtamd);
$t_z_inv = self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */
$rotate = self::fe_isnegative($t_z_inv);
$x_ = self::fe_copy($h->X);
$y_ = self::fe_copy($h->Y);
$den_inv = self::fe_copy($den2);
$x_ = self::fe_cmov($x_, $iy, $rotate);
$y_ = self::fe_cmov($y_, $ix, $rotate);
$den_inv = self::fe_cmov($den_inv, $eden, $rotate);
$x_z_inv = self::fe_mul($x_, $z_inv);
$y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv));
// fe25519_sub(s_, h->Z, y_);
// fe25519_mul(s_, den_inv, s_);
// fe25519_abs(s_, s_);
// fe25519_tobytes(s, s_);
return self::fe_tobytes(
self::fe_abs(
self::fe_mul(
$den_inv,
self::fe_sub($h->Z, $y_)
)
)
);
}
/**
* @param ParagonIE_Sodium_Core_Curve25519_Fe $t
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
*
* @throws SodiumException
*/
public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t)
{
$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
$onemsqd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd);
$d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
$sqdmone = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone);
$sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1);
$one = self::fe_1();
$r = self::fe_mul($sqrtm1, self::fe_sq($t)); /* r = sqrt(-1)*t^2 */
$u = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */
$c = self::fe_neg(self::fe_1()); /* c = -1 */
$rpd = self::fe_add($r, $d); /* rpd = r+d */
$v = self::fe_mul(
self::fe_sub(
$c,
self::fe_mul($r, $d)
),
$rpd
); /* v = (c-r*d)*(r+d) */
$result = self::ristretto255_sqrt_ratio_m1($u, $v);
$s = $result['x'];
$wasnt_square = 1 - $result['nonsquare'];
$s_prime = self::fe_neg(
self::fe_abs(
self::fe_mul($s, $t)
)
); /* s_prime = -|s*t| */
$s = self::fe_cmov($s, $s_prime, $wasnt_square);
$c = self::fe_cmov($c, $r, $wasnt_square);
// fe25519_sub(n, r, one); /* n = r-1 */
// fe25519_mul(n, n, c); /* n = c*(r-1) */
// fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */
// fe25519_sub(n, n, v); /* n = c*(r-1)*(d-1)^2-v */
$n = self::fe_sub(
self::fe_mul(
self::fe_mul(
self::fe_sub($r, $one),
$c
),
$sqdmone
),
$v
); /* n = c*(r-1)*(d-1)^2-v */
$w0 = self::fe_mul(
self::fe_add($s, $s),
$v
); /* w0 = 2s*v */
$w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */
$ss = self::fe_sq($s); /* ss = s^2 */
$w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */
$w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */
return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
self::fe_mul($w0, $w3),
self::fe_mul($w2, $w1),
self::fe_mul($w1, $w3),
self::fe_mul($w0, $w2)
);
}
/**
* @param string $h
* @return string
* @throws SodiumException
*/
public static function ristretto255_from_hash($h)
{
if (self::strlen($h) !== 64) {
throw new SodiumException('Hash must be 64 bytes');
}
//fe25519_frombytes(r0, h);
//fe25519_frombytes(r1, h + 32);
$r0 = self::fe_frombytes(self::substr($h, 0, 32));
$r1 = self::fe_frombytes(self::substr($h, 32, 32));
//ristretto255_elligator(&p0, r0);
//ristretto255_elligator(&p1, r1);
$p0 = self::ristretto255_elligator($r0);
$p1 = self::ristretto255_elligator($r1);
//ge25519_p3_to_cached(&p1_cached, &p1);
//ge25519_add_cached(&p_p1p1, &p0, &p1_cached);
$p_p1p1 = self::ge_add(
$p0,
self::ge_p3_to_cached($p1)
);
//ge25519_p1p1_to_p3(&p, &p_p1p1);
//ristretto255_p3_tobytes(s, &p);
return self::ristretto255_p3_tobytes(
self::ge_p1p1_to_p3($p_p1p1)
);
}
/**
* @param string $p
* @return int
* @throws SodiumException
*/
public static function is_valid_point($p)
{
$result = self::ristretto255_frombytes($p);
if ($result['res'] !== 0) {
return 0;
}
return 1;
}
/**
* @param string $p
* @param string $q
* @return string
* @throws SodiumException
*/
public static function ristretto255_add($p, $q)
{
$p_res = self::ristretto255_frombytes($p);
$q_res = self::ristretto255_frombytes($q);
if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
throw new SodiumException('Could not add points');
}
$p_p3 = $p_res['h'];
$q_p3 = $q_res['h'];
$q_cached = self::ge_p3_to_cached($q_p3);
$r_p1p1 = self::ge_add($p_p3, $q_cached);
$r_p3 = self::ge_p1p1_to_p3($r_p1p1);
return self::ristretto255_p3_tobytes($r_p3);
}
/**
* @param string $p
* @param string $q
* @return string
* @throws SodiumException
*/
public static function ristretto255_sub($p, $q)
{
$p_res = self::ristretto255_frombytes($p);
$q_res = self::ristretto255_frombytes($q);
if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
throw new SodiumException('Could not add points');
}
$p_p3 = $p_res['h'];
$q_p3 = $q_res['h'];
$q_cached = self::ge_p3_to_cached($q_p3);
$r_p1p1 = self::ge_sub($p_p3, $q_cached);
$r_p3 = self::ge_p1p1_to_p3($r_p1p1);
return self::ristretto255_p3_tobytes($r_p3);
}
/**
* @param int $hLen
* @param ?string $ctx
* @param string $msg
* @return string
* @throws SodiumException
* @psalm-suppress PossiblyInvalidArgument hash API
*/
protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg)
{
$h = array_fill(0, $hLen, 0);
$ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
if ($hLen > 0xff) {
throw new SodiumException('Hash must be less than 256 bytes');
}
if ($ctx_len > 0xff) {
$st = hash_init('sha256');
self::hash_update($st, "H2C-OVERSIZE-DST-");
self::hash_update($st, $ctx);
$ctx = hash_final($st, true);
$ctx_len = 32;
}
$t = array(0, $hLen, 0);
$ux = str_repeat("\0", 64);
$st = hash_init('sha256');
self::hash_update($st, $ux);
self::hash_update($st, $msg);
self::hash_update($st, self::intArrayToString($t));
self::hash_update($st, $ctx);
self::hash_update($st, self::intToChr($ctx_len));
$u0 = hash_final($st, true);
for ($i = 0; $i < $hLen; $i += 64) {
$ux = self::xorStrings($ux, $u0);
++$t[2];
$st = hash_init('sha256');
self::hash_update($st, $ux);
self::hash_update($st, self::intToChr($t[2]));
self::hash_update($st, $ctx);
self::hash_update($st, self::intToChr($ctx_len));
$ux = hash_final($st, true);
$amount = min($hLen - $i, 64);
for ($j = 0; $j < $amount; ++$j) {
$h[$i + $j] = self::chrToInt($ux[$i]);
}
}
return self::intArrayToString(array_slice($h, 0, $hLen));
}
/**
* @param int $hLen
* @param ?string $ctx
* @param string $msg
* @return string
* @throws SodiumException
* @psalm-suppress PossiblyInvalidArgument hash API
*/
protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg)
{
$h = array_fill(0, $hLen, 0);
$ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
if ($hLen > 0xff) {
throw new SodiumException('Hash must be less than 256 bytes');
}
if ($ctx_len > 0xff) {
$st = hash_init('sha256');
self::hash_update($st, "H2C-OVERSIZE-DST-");
self::hash_update($st, $ctx);
$ctx = hash_final($st, true);
$ctx_len = 32;
}
$t = array(0, $hLen, 0);
$ux = str_repeat("\0", 128);
$st = hash_init('sha512');
self::hash_update($st, $ux);
self::hash_update($st, $msg);
self::hash_update($st, self::intArrayToString($t));
self::hash_update($st, $ctx);
self::hash_update($st, self::intToChr($ctx_len));
$u0 = hash_final($st, true);
for ($i = 0; $i < $hLen; $i += 128) {
$ux = self::xorStrings($ux, $u0);
++$t[2];
$st = hash_init('sha512');
self::hash_update($st, $ux);
self::hash_update($st, self::intToChr($t[2]));
self::hash_update($st, $ctx);
self::hash_update($st, self::intToChr($ctx_len));
$ux = hash_final($st, true);
$amount = min($hLen - $i, 128);
for ($j = 0; $j < $amount; ++$j) {
$h[$i + $j] = self::chrToInt($ux[$i]);
}
}
return self::intArrayToString(array_slice($h, 0, $hLen));
}
/**
* @param int $hLen
* @param ?string $ctx
* @param string $msg
* @param int $hash_alg
* @return string
* @throws SodiumException
*/
public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg)
{
switch ($hash_alg) {
case self::CORE_H2C_SHA256:
return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg);
case self::CORE_H2C_SHA512:
return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg);
default:
throw new SodiumException('Invalid H2C hash algorithm');
}
}
/**
* @param ?string $ctx
* @param string $msg
* @param int $hash_alg
* @return string
* @throws SodiumException
*/
protected static function _string_to_element($ctx, $msg, $hash_alg)
{
return self::ristretto255_from_hash(
self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg)
);
}
/**
* @return string
* @throws SodiumException
* @throws Exception
*/
public static function ristretto255_random()
{
return self::ristretto255_from_hash(
ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES)
);
}
/**
* @return string
* @throws SodiumException
*/
public static function ristretto255_scalar_random()
{
return self::scalar_random();
}
/**
* @param string $s
* @return string
* @throws SodiumException
*/
public static function ristretto255_scalar_complement($s)
{
return self::scalar_complement($s);
}
/**
* @param string $s
* @return string
*/
public static function ristretto255_scalar_invert($s)
{
return self::sc25519_invert($s);
}
/**
* @param string $s
* @return string
* @throws SodiumException
*/
public static function ristretto255_scalar_negate($s)
{
return self::scalar_negate($s);
}
/**
* @param string $x
* @param string $y
* @return string
*/
public static function ristretto255_scalar_add($x, $y)
{
return self::scalar_add($x, $y);
}
/**
* @param string $x
* @param string $y
* @return string
*/
public static function ristretto255_scalar_sub($x, $y)
{
return self::scalar_sub($x, $y);
}
/**
* @param string $x
* @param string $y
* @return string
*/
public static function ristretto255_scalar_mul($x, $y)
{
return self::sc25519_mul($x, $y);
}
/**
* @param string $ctx
* @param string $msg
* @param int $hash_alg
* @return string
* @throws SodiumException
*/
public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg)
{
$h = array_fill(0, 64, 0);
$h_be = self::stringToIntArray(
self::h2c_string_to_hash(
self::HASH_SC_L, $ctx, $msg, $hash_alg
)
);
for ($i = 0; $i < self::HASH_SC_L; ++$i) {
$h[$i] = $h_be[self::HASH_SC_L - 1 - $i];
}
return self::ristretto255_scalar_reduce(self::intArrayToString($h));
}
/**
* @param string $s
* @return string
*/
public static function ristretto255_scalar_reduce($s)
{
return self::sc_reduce($s);
}
/**
* @param string $n
* @param string $p
* @return string
* @throws SodiumException
*/
public static function scalarmult_ristretto255($n, $p)
{
if (self::strlen($n) !== 32) {
throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.');
}
if (self::strlen($p) !== 32) {
throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.');
}
$result = self::ristretto255_frombytes($p);
if ($result['res'] !== 0) {
throw new SodiumException('Could not multiply points');
}
$P = $result['h'];
$t = self::stringToIntArray($n);
$t[31] &= 0x7f;
$Q = self::ge_scalarmult(self::intArrayToString($t), $P);
$q = self::ristretto255_p3_tobytes($Q);
if (ParagonIE_Sodium_Compat::is_zero($q)) {
throw new SodiumException('An unknown error has occurred');
}
return $q;
}
/**
* @param string $n
* @return string
* @throws SodiumException
*/
public static function scalarmult_ristretto255_base($n)
{
$t = self::stringToIntArray($n);
$t[31] &= 0x7f;
$Q = self::ge_scalarmult_base(self::intArrayToString($t));
$q = self::ristretto255_p3_tobytes($Q);
if (ParagonIE_Sodium_Compat::is_zero($q)) {
throw new SodiumException('An unknown error has occurred');
}
return $q;
}
}
Salsa20.php 0000644 00000000142 15153624057 0006467 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class Salsa20 extends \ParagonIE_Sodium_Core_Salsa20
{
}
SecretStream/State.php 0000644 00000007050 15153624057 0010750 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core_SecretStream_State
*/
class ParagonIE_Sodium_Core_SecretStream_State
{
/** @var string $key */
protected $key;
/** @var int $counter */
protected $counter;
/** @var string $nonce */
protected $nonce;
/** @var string $_pad */
protected $_pad;
/**
* ParagonIE_Sodium_Core_SecretStream_State constructor.
* @param string $key
* @param string|null $nonce
*/
public function __construct($key, $nonce = null)
{
$this->key = $key;
$this->counter = 1;
if (is_null($nonce)) {
$nonce = str_repeat("\0", 12);
}
$this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);;
$this->_pad = str_repeat("\0", 4);
}
/**
* @return self
*/
public function counterReset()
{
$this->counter = 1;
$this->_pad = str_repeat("\0", 4);
return $this;
}
/**
* @return string
*/
public function getKey()
{
return $this->key;
}
/**
* @return string
*/
public function getCounter()
{
return ParagonIE_Sodium_Core_Util::store32_le($this->counter);
}
/**
* @return string
*/
public function getNonce()
{
if (!is_string($this->nonce)) {
$this->nonce = str_repeat("\0", 12);
}
if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) {
$this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT);
}
return $this->nonce;
}
/**
* @return string
*/
public function getCombinedNonce()
{
return $this->getCounter() .
ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8);
}
/**
* @return self
*/
public function incrementCounter()
{
++$this->counter;
return $this;
}
/**
* @return bool
*/
public function needsRekey()
{
return ($this->counter & 0xffff) === 0;
}
/**
* @param string $newKeyAndNonce
* @return self
*/
public function rekey($newKeyAndNonce)
{
$this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32);
$this->nonce = str_pad(
ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32),
12,
"\0",
STR_PAD_RIGHT
);
return $this;
}
/**
* @param string $str
* @return self
*/
public function xorNonce($str)
{
$this->nonce = ParagonIE_Sodium_Core_Util::xorStrings(
$this->getNonce(),
str_pad(
ParagonIE_Sodium_Core_Util::substr($str, 0, 8),
12,
"\0",
STR_PAD_RIGHT
)
);
return $this;
}
/**
* @param string $string
* @return self
*/
public static function fromString($string)
{
$state = new ParagonIE_Sodium_Core_SecretStream_State(
ParagonIE_Sodium_Core_Util::substr($string, 0, 32)
);
$state->counter = ParagonIE_Sodium_Core_Util::load_4(
ParagonIE_Sodium_Core_Util::substr($string, 32, 4)
);
$state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36, 12);
$state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48, 8);
return $state;
}
/**
* @return string
*/
public function toString()
{
return $this->key .
$this->getCounter() .
$this->nonce .
$this->_pad;
}
}
SipHash.php 0000644 00000000142 15153624057 0006621 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class SipHash extends \ParagonIE_Sodium_Core_SipHash
{
}
Util.php 0000644 00000000134 15153624057 0006200 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class Util extends \ParagonIE_Sodium_Core_Util
{
}
X25519.php 0000644 00000000140 15153624057 0006075 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class X25519 extends \ParagonIE_Sodium_Core_X25519
{
}
XChaCha20.php 0000644 00000000146 15153624057 0006667 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class XChaCha20 extends \ParagonIE_Sodium_Core_XChaCha20
{
}
XSalsa20.php 0000644 00000002533 15153624057 0006625 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core_XSalsa20', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core_XSalsa20
*/
abstract class ParagonIE_Sodium_Core_XSalsa20 extends ParagonIE_Sodium_Core_HSalsa20
{
/**
* Expand a key and nonce into an xsalsa20 keystream.
*
* @internal You should not use this directly from another application
*
* @param int $len
* @param string $nonce
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function xsalsa20($len, $nonce, $key)
{
$ret = self::salsa20(
$len,
self::substr($nonce, 16, 8),
self::hsalsa20($nonce, $key)
);
return $ret;
}
/**
* Encrypt a string with XSalsa20. Doesn't provide integrity.
*
* @internal You should not use this directly from another application
*
* @param string $message
* @param string $nonce
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function xsalsa20_xor($message, $nonce, $key)
{
return self::xorStrings(
$message,
self::xsalsa20(
self::strlen($message),
$nonce,
$key
)
);
}
}
Xsalsa20.php 0000644 00000000144 15153701236 0006654 0 ustar 00 <?php
namespace ParagonIE\Sodium\Core;
class Xsalsa20 extends \ParagonIE_Sodium_Core_XSalsa20
{
}
Assets.php 0000644 00000036663 15154027146 0006542 0 ustar 00 <?php
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles the loading of our file assets.
*
* @since 1.0.0
*/
class Assets {
/**
* Whether we should load dev scripts.
*
* @since 1.0.0
*
* @var boolean|null
*/
private $shouldLoadDevScripts = null;
/**
* The script handle to use for asset enqueuing.
*
* @since 1.0.0
*
* @var string
*/
private $scriptHandle = 'aioseo-broken-link-checker';
/**
* Holds the location of the manifest file.
*
* @since 1.0.0
*
* @var string
*/
private $manifestFile = '';
/**
* True if we are in a dev environment. This mirrors the global isDev.
*
* @since 1.0.0
*
* @var bool
*/
private $isDev = false;
/**
* Asset handles that should load as regular JS and not as modern JS module.
*
* @since 1.0.0
*
* @var array An array of handles.
*/
private $noModuleTag = [];
/**
* Core class instance.
*
* @since 1.1.0
*
* @var Core
*/
public $core = null;
/**
* The plugin version.
*
* @since 1.1.0
*
* @var int
*/
public $version = 0;
/**
* The domain.
*
* @since 1.1.0
*
* @var string
*/
public $domain = '';
/**
* The port.
*
* @since 1.1.0
*
* @var int
*/
public $port = 0;
/**
* Class constructor.
*
* @since 1.0.0
*
* @param Core $core The AIOSEO Core class.
*/
public function __construct( $core ) {
$this->core = $core;
$this->version = aioseoBrokenLinkChecker()->version;
$this->manifestFile = AIOSEO_BROKEN_LINK_CHECKER_DIR . '/dist/manifest.php';
$this->isDev = aioseoBrokenLinkChecker()->isDev;
if ( $this->isDev ) {
$this->domain = getenv( 'VITE_AIOSEO_BROKEN_LINK_CHECKER_DOMAIN' );
$this->port = getenv( 'VITE_AIOSEO_BROKEN_LINK_CHECKER_DEV_PORT' );
}
add_filter( 'script_loader_tag', [ $this, 'scriptLoaderTag' ], 10, 3 );
}
/**
* The asset to load.
*
* @since 1.0.0
*
* @param string $asset The asset to load.
* @param array $dependencies An array of dependencies.
* @param mixed $data Any data to be localized.
* @param string $objectName The object name to use when localizing.
* @return void
*/
public function load( $asset, $dependencies = [], $data = null, $objectName = 'aioseoBrokenLinkChecker' ) {
$this->jsPreloadImports( $asset );
$this->loadCss( $asset );
$this->enqueueJs( $asset, $dependencies, $data, $objectName );
}
/**
* Filter the script loader tag if this is our script.
*
* @since 1.0.0
*
* @param string $tag The tag that is going to be output.
* @param string $handle The handle for the script.
* @return string The modified tag.
*/
public function scriptLoaderTag( $tag, $handle, $src ) {
if ( $this->skipModuleTag( $handle ) ) {
return $tag;
}
$tag = str_replace( $src, $this->normalizeAssetsHost( $src ), $tag );
// Remove the type and re-add it as module.
$tag = preg_replace( '/type=[\'"].*?[\'"]/', '', (string) $tag );
$tag = preg_replace( '/<script/', '<script type="module"', (string) $tag );
return $tag;
}
/**
* Preload JS imports.
*
* @since 1.0.0
*
* @param string $asset The asset to load imports for.
* @return void
*/
private function jsPreloadImports( $asset ) {
static $urls = []; // Prevent script from being loaded multiple times.
$res = '';
foreach ( $this->importsUrls( $asset ) as $url ) {
if ( isset( $urls[ $url ] ) ) {
continue;
}
$urls[ $url ] = true;
$res .= '<link rel="modulepreload" href="' . esc_attr( $url ) . "\">\n";
}
$allowedHtml = [
'link' => [
'rel' => [],
'href' => []
]
];
if ( ! empty( $res ) ) {
if ( ! function_exists( 'wp_enqueue_script_module' ) ) {
add_action( 'admin_head', function () use ( &$res, $allowedHtml ) {
echo wp_kses( $res, $allowedHtml );
} );
add_action( 'wp_head', function () use ( &$res, $allowedHtml ) {
echo wp_kses( $res, $allowedHtml );
} );
} else {
add_action( 'admin_print_footer_scripts', function () use ( &$res, $allowedHtml ) {
echo wp_kses( $res, $allowedHtml );
}, 1000 );
}
}
}
/**
* Loads CSS for an asset from the manifest file.
*
* @since 1.0.0
*
* @param string $asset The script to load CSS for.
* @return void
*/
private function loadCss( $asset ) {
if ( $this->shouldLoadDev() ) {
return;
}
foreach ( $this->getCssUrls( $asset ) as $file => $url ) {
wp_enqueue_style( $this->cssHandle( $file ), $url, [], $this->version );
}
}
/**
* Register a CSS asset.
*
* @since 1.0.0
*
* @param string $asset The script to load CSS for.
* @param array $dependencies An array of dependencies.
* @param string $devPath The file's dev path.
* @return void
*/
public function registerCss( $asset, $dependencies = [], $devPath = '' ) {
$handle = $this->cssHandle( $asset );
if ( wp_style_is( $handle, 'registered' ) ) {
return;
}
$devPath = $devPath ?: $asset;
$url = $this->shouldLoadDev()
? $this->getDevUrl() . ltrim( $devPath, '/' )
: $this->assetUrl( $asset );
if ( ! $url ) {
return;
}
wp_register_style( $handle, $url, $dependencies, $this->version );
}
/**
* Enqueue css.
*
* @since 1.0.0
*
* @param string $asset The css to load.
* @param string $devPath The file's dev path.
* @param array $dependencies An array of dependencies.
* @return void
*/
public function enqueueCss( $asset, $dependencies = [], $devPath = '' ) {
$this->registerCss( $asset, $dependencies, $devPath );
$handle = $this->cssHandle( $asset );
if ( wp_style_is( $handle, 'enqueued' ) ) {
return;
}
wp_enqueue_style( $handle );
}
/**
* Register the JS to enqueue.
*
* @since 1.0.0
*
* @param string $asset The script to load.
* @param array $dependencies An array of dependencies.
* @param mixed $data Any data to be localized.
* @param string $objectName The object name to use when localizing.
* @return void
*/
public function registerJs( $asset, $dependencies = [], $data = null, $objectName = 'aioseoBrokenLinkChecker' ) {
$handle = $this->jsHandle( $asset );
if ( wp_script_is( $handle, 'registered' ) ) {
return;
}
$url = $this->shouldLoadDev()
? $this->getDevUrl() . ltrim( $asset, '/' )
: $this->jsUrl( $asset );
if ( ! $url ) {
return;
}
wp_register_script( $handle, $url, $dependencies, $this->version, true );
if ( empty( $data ) ) {
return;
}
wp_localize_script(
$handle,
$objectName,
$data
);
}
/**
* Register the JS to enqueue.
*
* @since 1.0.0
*
* @param string $asset The script to load.
* @param array $dependencies An array of dependencies.
* @param mixed $data Any data to be localized.
* @param string $objectName The object name to use when localizing.
* @return void
*/
public function enqueueJs( $asset, $dependencies = [], $data = null, $objectName = 'aioseoBrokenLinkChecker' ) {
$this->registerJs( $asset, $dependencies, $data, $objectName );
$handle = $this->jsHandle( $asset );
if ( wp_script_is( $handle, 'enqueued' ) ) {
return;
}
wp_enqueue_script( $handle );
}
/**
* Return the dev URL.
*
* @since 1.0.0
*
* @return string The dev URL.
*/
private function getDevUrl() {
$protocol = is_ssl() ? 'https://' : 'http://';
return $protocol . $this->domain . ':' . $this->port . '/';
}
/**
* Get the asset URL.
*
* @since 1.0.0
*
* @param string $asset The asset to find the URL for.
* @return string The URL for the asset.
*/
private function assetUrl( $asset ) {
$assetManifest = $this->getAssetManifestItem( $asset );
return ! empty( $assetManifest['file'] )
? $this->basePath() . $assetManifest['file']
: $this->basePath() . ltrim( $asset, '/' );
}
/**
* Get the JS URL.
*
* @since 1.0.0
*
* @param string $asset The asset to find the URL for.
* @return string The URL for the asset.
*/
public function jsUrl( $asset ) {
$manifestAsset = $this->getManifestItem( $asset );
return ! empty( $manifestAsset['file'] )
? $this->basePath() . $manifestAsset['file']
: $this->basePath() . ltrim( $asset, '/' );
}
/**
* Get an item from the manifest.
*
* @since 1.0.0
*
* @param string $asset The asset to find.
* @return string Manifest object.
*/
private function getManifestItem( $asset ) {
$manifest = $this->getManifest();
$asset = ltrim( $asset, '/' );
return isset( $manifest[ $asset ] ) ? $manifest[ $asset ] : null;
}
/**
* Get the CSS asset handle.
*
* @since 1.0.0
*
* @param string $asset The asset to find the handle for.
* @return string The asset handle.
*/
public function cssHandle( $asset ) {
return "{$this->scriptHandle}/css/$asset";
}
/**
* Get the JS asset handle.
*
* @since 1.0.0
*
* @param string $asset The asset to find the handle for.
* @return string The asset handle.
*/
public function jsHandle( $asset = '' ) {
return "{$this->scriptHandle}/js/$asset";
}
/**
* Get the manifest to load assets from.
*
* @since 1.0.0
*
* @return array An array of files.
*/
private function getManifest() {
static $file = null;
if ( $file ) {
return $file;
}
$manifestJson = ''; // This is set in the view.
if ( file_exists( $this->manifestFile ) ) {
require_once $this->manifestFile;
}
$file = json_decode( $manifestJson, true );
return $file;
}
/**
* Get an item from the asset manifest.
*
* @since 1.0.0
*
* @param string $item An item to retrieve.
* @return string|null The asset item.
*/
private function getAssetManifestItem( $item ) {
$assetManifest = $this->getManifest();
return ! empty( $assetManifest[ $item ] ) ? $assetManifest[ $item ] : null;
}
/**
* Get an asset's array of URLs to import.
*
* @since 1.0.0
*
* @param string $asset The asset to find imports for.
* @return array An array of imports.
*/
private function importsUrls( $asset ) {
$urls = [];
$manifestAsset = $this->getManifestItem( $asset );
if ( ! empty( $manifestAsset['imports'] ) ) {
foreach ( $manifestAsset['imports'] as $import ) {
$importAsset = $this->getManifestItem( $import );
if ( ! empty( $importAsset['file'] ) ) {
$urls[] = $this->getPublicUrlBase() . $importAsset['file'];
// Load the import's CSS if any.
$this->loadCss( $import );
}
}
}
return $urls;
}
/**
* Returns an asset's CSS urls.
*
* @since 1.0.0
*
* @param string $asset The asset to find CSS URLs for.
* @return array An array of CSS URLs to load.
*/
private function getCssUrls( $asset ) {
$urls = [];
$manifestAsset = $this->getManifestItem( $asset );
if ( ! empty( $manifestAsset['css'] ) ) {
foreach ( $manifestAsset['css'] as $file ) {
$urls[ $file ] = $this->getPublicUrlBase() . $file;
}
}
return $urls;
}
/**
* Check if we should load the dev watcher scripts.
*
* @since 1.0.0
*
* @return boolean True if we should load the dev watcher scripts.
*/
private function shouldLoadDev() {
if ( null !== $this->shouldLoadDevScripts ) {
return $this->shouldLoadDevScripts;
}
if (
! $this->isDev ||
(
defined( 'AIOSEO_BROKEN_LINK_CHECKER_LOAD_DEV_SCRIPTS' ) &&
false === AIOSEO_BROKEN_LINK_CHECKER_LOAD_DEV_SCRIPTS
)
) {
$this->shouldLoadDevScripts = false;
return $this->shouldLoadDevScripts;
}
if ( ! $this->domain && ! $this->port ) {
$this->shouldLoadDevScripts = false;
return $this->shouldLoadDevScripts;
}
set_error_handler( function() {} ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler
$connection = fsockopen( $this->domain, $this->port ); // phpcs:ignore WordPress.WP.AlternativeFunctions
restore_error_handler();
if ( ! $connection ) {
$this->shouldLoadDevScripts = false;
return $this->shouldLoadDevScripts;
}
$this->shouldLoadDevScripts = true;
return $this->shouldLoadDevScripts;
}
/**
* Get the path for the assets.
*
* @since 1.0.0
*
* @param bool $maybeDev Whether to try and load dev scripts.
* @return string The path for the assets.
*/
public function getAssetsPath( $maybeDev = true ) {
return $maybeDev && $this->shouldLoadDev()
? $this->getDevUrl()
: $this->basePath();
}
/**
* Finds out if a handle should be loaded as regular JS and not as modern JS module.
*
* @since 1.0.0
*
* @param string $handle The script handle.
* @return bool Should the module tag be skipped.
*/
public function skipModuleTag( $handle ) {
if ( ! aioseoBrokenLinkChecker()->helpers->stringContains( $handle, $this->jsHandle( '' ) ) ) {
return true;
}
foreach ( $this->noModuleTag as $tag ) {
if ( aioseoBrokenLinkChecker()->helpers->stringContains( $handle, $tag ) ) {
return true;
}
}
return false;
}
/**
* Normalize the assets host. Some sites manually set the WP_PLUGINS_URL
* and if that domain has www. and the site_url does not, then it will fail to load
* our assets. This doesn't fix the issue 100% because it will still fail on
* sub-domains that don't have the proper CORS headers. Those sites will need
* manual fixes.
*
* 4.1.10
*
* @param string $path The path to normalize.
* @return string The normalized path.
*/
public function normalizeAssetsHost( $path ) {
static $paths = [];
if ( isset( $paths[ $path ] ) ) {
return apply_filters( 'aioseo_blc_normalize_assets_host', $paths[ $path ] );
}
// We need to verify the domain on the $path attribute matches
// what's in site_url() for our assets or they won't load.
$siteUrl = site_url();
$siteUrlEscaped = aioseoBrokenLinkChecker()->helpers->escapeRegex( $siteUrl );
if ( preg_match( "/^$siteUrlEscaped/i", (string) $path ) ) {
$paths[ $path ] = $path;
return apply_filters( 'aioseo_blc_normalize_assets_host', $paths[ $path ] );
}
// We now know that the path doesn't contain the site_url().
$newPath = $path;
$siteUrlParsed = wp_parse_url( $siteUrl );
$host = aioseoBrokenLinkChecker()->helpers->escapeRegex( str_replace( 'www.', '', $siteUrlParsed['host'] ) );
$scheme = aioseoBrokenLinkChecker()->helpers->escapeRegex( $siteUrlParsed['scheme'] );
$siteUrlHasWww = preg_match( "/^{$scheme}:\/\/www\.$host/", (string) $siteUrl );
$pathHasWww = preg_match( "/^{$scheme}:\/\/www\.$host/", (string) $path );
// Check if the path contains www.
if ( $pathHasWww && ! $siteUrlHasWww ) {
// If the path contains www., we want to strip it out.
$newPath = preg_replace( "/^({$scheme}:\/\/)(www\.)($host)/", '$1$3', (string) $path );
}
// Check if the site_url contains www.
if ( $siteUrlHasWww && ! $pathHasWww ) {
// If the site_url contains www., we want to add it in to the path.
$newPath = preg_replace( "/^({$scheme}:\/\/)($host)/", '$1www.$2', (string) $path );
}
$paths[ $path ] = $newPath;
return apply_filters( 'aioseo_blc_normalize_assets_host', $paths[ $path ] );
}
/**
* Returns the public URL base.
*
* @since 1.0.0
*
* @return string The URL base.
*/
private function getPublicUrlBase() {
return $this->shouldLoadDev() ? $this->getDevUrl() . 'dist/assets/' : $this->basePath();
}
/**
* Returns the base path URL.
*
* @since 1.0.0
*
* @return string The base path URL.
*/
private function basePath() {
return $this->normalizeAssetsHost( plugins_url( 'dist/assets/', AIOSEO_BROKEN_LINK_CHECKER_FILE ) );
}
} Cache.php 0000644 00000014221 15154027146 0006265 0 ustar 00 <?php
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles our cache.
*
* @since 1.0.0
*/
class Cache {
/**
* The name of our cache table.
*
* @since 1.0.0
*
* @var string
*/
private $table = 'aioseo_blc_cache';
/**
* Our cache.
*
* @since 1.0.0
*
* @var array
*/
private static $cache = [];
/**
* Prefix for this cache.
*
* @since 1.0.0
*
* @var string
*/
protected $prefix = 'aioseo_blc_';
/**
* Class constructor.
*
* @since 4.7.8
*/
public function __construct() {
add_action( 'init', [ $this, 'checkIfTableExists' ] ); // This needs to run on init because the DB
// class gets instantiated along with the cache class.
}
/**
* Checks if the cache table exists and creates it if it doesn't.
*
* @since 4.7.8
*
* @return void
*/
public function checkIfTableExists() {
if ( ! aioseoBrokenLinkChecker()->core->db->tableExists( $this->table ) ) {
aioseoBrokenLinkChecker()->preUpdates->createCacheTable();
}
}
/**
* Returns the cache value if it exists and isn't expired.
*
* @since 1.0.0
*
* @param string $key The key name. Use a '%' for a LIKE query.
* @return mixed The value or null if the cache does not exist.
*/
public function get( $key ) {
$key = $this->prepareKey( $key );
if ( isset( self::$cache[ $key ] ) ) {
return self::$cache[ $key ];
}
// Check if we're supposed to do a LIKE get.
$isLikeGet = preg_match( '/%/', (string) $key );
$result = aioseoBrokenLinkChecker()->core->db
->start( $this->table )
->select( '`key`, `value`' )
->whereRaw( '( `expiration` IS NULL OR `expiration` > \'' . aioseoBrokenLinkChecker()->helpers->timeToMysql( time() ) . '\' )' );
$isLikeGet ?
$result->whereRaw( '`key` LIKE \'' . $key . '\'' ) :
$result->where( 'key', $key );
$result->output( ARRAY_A )->run();
// If we have nothing in the cache, let's return null.
$values = $result->nullSet() ? null : $result->result();
// If we have something, let's normalize it.
if ( $values ) {
foreach ( $values as &$value ) {
$value['value'] = aioseoBrokenLinkChecker()->helpers->maybeUnserialize( $value['value'] );
}
// Return only the single cache value.
if ( ! $isLikeGet ) {
$values = $values[0]['value'];
}
}
// Return values without a static cache.
// This is here because clearing the LIKE cache is not simple.
if ( $isLikeGet ) {
return $values;
}
self::$cache[ $key ] = $values;
return self::$cache[ $key ];
}
/**
* Updates the given cache or creates it if it doesn't exist.
*
* @since 1.0.0
*
* @param string $key The key name.
* @param mixed $value The value.
* @param int $expiration The expiration time in seconds. Defaults to 24 hours. 0 to no expiration.
* @return void
*/
public function update( $key, $value, $expiration = DAY_IN_SECONDS ) {
// If the value is null we'll convert it and give it a shorter expiration.
if ( null === $value ) {
$value = false;
$expiration = 10 * MINUTE_IN_SECONDS;
}
$value = serialize( $value );
$expiration = 0 < $expiration ? aioseoBrokenLinkChecker()->helpers->timeToMysql( time() + $expiration ) : null;
aioseoBrokenLinkChecker()->core->db->insert( $this->table )
->set( [
'key' => $this->prepareKey( $key ),
'value' => $value,
'expiration' => $expiration,
'created' => aioseoBrokenLinkChecker()->helpers->timeToMysql( time() ),
'updated' => aioseoBrokenLinkChecker()->helpers->timeToMysql( time() )
] )->onDuplicate( [
'value' => $value,
'expiration' => $expiration,
'updated' => aioseoBrokenLinkChecker()->helpers->timeToMysql( time() )
] )
->run();
$this->clearStatic( $key );
}
/**
* Deletes the cache record with the given key.
*
* @since 1.0.0
*
* @param string $key The key.
* @return void
*/
public function delete( $key ) {
$key = $this->prepareKey( $key );
aioseoBrokenLinkChecker()->core->db->delete( $this->table )
->where( 'key', $key )
->run();
$this->clearStatic( $key );
}
/**
* Prepares the key before using the cache.
*
* @since 1.0.0
*
* @param string $key The key to prepare.
* @return string The prepared key.
*/
private function prepareKey( $key ) {
$key = trim( $key );
$key = $this->prefix && 0 !== strpos( $key, $this->prefix ) ? $this->prefix . $key : $key;
if ( aioseoBrokenLinkChecker()->helpers->isDev() && 80 < mb_strlen( $key, 'UTF-8' ) ) {
throw new \Exception( 'You are using a cache key that is too large, shorten your key and try again: [' . esc_html( $key ) . ']' );
}
return $key;
}
/**
* Clears all of our cache.
*
* @since 1.0.0
*
* @return void
*/
public function clear() {
// Bust the tableExists and columnExists cache.
aioseoBrokenLinkChecker()->internalOptions->database->installedTables = '';
if ( $this->prefix ) {
$this->clearPrefix( '' );
return;
}
aioseoBrokenLinkChecker()->core->db->truncate( $this->table )->run();
$this->clearStatic();
}
/**
* Clears all of our cache under a certain prefix.
*
* @since 1.0.0
*
* @param string $prefix A prefix to clear or empty to clear everything.
* @return void
*/
public function clearPrefix( $prefix ) {
$prefix = $this->prepareKey( $prefix );
aioseoBrokenLinkChecker()->core->db->delete( $this->table )
->whereRaw( "`key` LIKE '$prefix%'" )
->run();
$this->clearStaticPrefix( $prefix );
}
/**
* Clears all of our static in-memory cache of a prefix.
*
* @since 1.0.0
*
* @param string $prefix The prefix to clear.
* @return void
*/
private function clearStaticPrefix( $prefix ) {
$prefix = $this->prepareKey( $prefix );
foreach ( array_keys( self::$cache ) as $key ) {
if ( 0 === strpos( $key, $prefix ) ) {
unset( self::$cache[ $key ] );
}
}
}
/**
* Clears all of our static in-memory cache.
*
* @since 1.0.0
*
* @param string $key The key to clear.
* @return void
*/
private function clearStatic( $key = null ) {
if ( empty( $key ) ) {
self::$cache = [];
return;
}
unset( self::$cache[ $this->prepareKey( $key ) ] );
}
} Core.php 0000644 00000002637 15154027146 0006162 0 ustar 00 <?php
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\BrokenLinkChecker\Options;
use AIOSEO\BrokenLinkChecker\Utils;
/**
* Loads core classes.
*
* @since 1.0.0
*/
class Core {
/**
* DB class instance.
*
* @since 1.1.0
*
* @var Database
*/
public $db = null;
/**
* Filesystem class instance.
*
* @since 1.1.0
*
* @var Filesystem
*/
public $fs = null;
/**
* Assets class instance.
*
* @since 1.1.0
*
* @var Assets
*/
public $assets = null;
/**
* Cache class instance.
*
* @since 1.1.0
*
* @var Cache
*/
public $cache = null;
/**
* NetworkCache class instance.
*
* @since 1.1.0
*
* @var NetworkCache
*/
public $networkCache = null;
/**
* Options Cache class instance.
*
* @since 1.1.0
*
* @var \AIOSEO\BrokenLinkChecker\Options\Cache
*/
public $optionsCache = null;
/**
* Uninstall class instance.
*
* @since 1.1.0
*
* @var Uninstall
*/
public $uninstall = null;
/**
* Class constructor.
*
* @since 1.0.0
*/
public function __construct() {
$this->db = new Database();
$this->fs = new Filesystem( $this );
$this->assets = new Assets( $this );
$this->cache = new Cache();
$this->networkCache = new NetworkCache();
$this->optionsCache = new Options\Cache();
$this->uninstall = new Uninstall();
}
} Database.php 0000644 00000117531 15154027146 0006776 0 ustar 00 <?php
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Builds queries for the database and returns results.
*
* @since 1.0.0
*/
class Database {
/**
* List of custom tables we support.
*
* @since 1.0.0
*
* @var array
*/
public $customTables = [
'aioseo_blc_cache',
'aioseo_blc_links',
'aioseo_blc_link_status',
'aioseo_blc_notifications',
'aioseo_blc_posts'
];
/**
* Holds the global $wpdb instance.
*
* @since 1.0.0
*
* @var \wpdb
*/
public $db = null;
/**
* Holds the $wpdb prefix.
*
* @since 1.0.0
*
* @var string
*/
public $prefix = '';
/**
* The database table in use by this query.
*
* @since 1.0.0
*
* @var string
*/
public $table = '';
/**
* The sql statement (SELECT, INSERT, UPDATE, DELETE, etc.).
*
* @since 1.0.0
*
* @var string
*/
private $statement = '';
/**
* The limit clause for the sql query.
*
* @since 1.0.0
*
* @var string
*/
private $limit = '';
/**
* The group clause for the sql query.
*
* @since 1.0.0
*
* @var array
*/
private $group = [];
/**
* The order by clause for the sql query.
*
* @since 1.0.0
*
* @var array
*/
private $order = [];
/**
* The select clause for the sql query.
*
* @since 1.0.0
*
* @var array
*/
private $select = [];
/**
* The set clause for the sql query.
*
* @since 1.0.0
*
* @var array
*/
private $set = [];
/**
* Duplicate clause for the INSERT query.
*
* @since 1.0.0
*
* @var array
*/
private $onDuplicate = [];
/**
* Ignore clause for the INSERT query.
*
* @since 1.0.0
*
* @var array
*/
private $ignore = false;
/**
* The where clause for the sql query.
*
* @since 1.0.0
*
* @var array
*/
private $where = [];
/**
* The union clause for the sql query.
*
* @since 1.0.0
*
* @var array
*/
private $union = [];
/**
* The JOIN clause for the SQL query.
*
* @since 1.1.0
*
* @var array
*/
private $join = [];
/**
* Determines whether the select statement should be distinct.
*
* @since 1.0.0
*
* @var bool
*/
private $distinct = false;
/**
* The order by direction for the query.
*
* @since 1.0.0
*
* @var string
*/
private $orderDirection = 'ASC';
/**
* The query string is populated after the __toString function is run.
*
* @since 1.0.0
*
* @var string
*/
private $query = '';
/**
* The sql query results are stored here.
*
* @since 1.0.0
*
* @var mixed
*/
private $result = [];
/**
* The method in which $wpdb will output results.
*
* @since 1.0.0
*
* @var string
*/
private $output = 'OBJECT';
/**
* Whether or not to strip tags.
*
* @since 1.0.0
*
* @var boolean
*/
private $stripTags = false;
/**
* Set which option to use to escape the sql query.
*
* @since 1.0.0
*
* @var integer
*/
protected $escapeOptions = 0;
/**
* A cache of all queries and their results.
*
* @var array
*/
private $cache = [];
/**
* Whether or not to reset the cached results.
*
* @var boolean
*/
private $shouldResetCache = false;
/**
* Constant for escape options.
*
* @since 1.0.0
*
* @var integer
*/
const ESCAPE_FORCE = 2;
/**
* Constant for escape options.
*
* @since 1.0.0
*
* @var integer
*/
const ESCAPE_STRIP_HTML = 4;
/**
* Constant for escape options.
*
* @since 1.0.0
*
* @var integer
*/
const ESCAPE_QUOTE = 8;
/**
* List of model class instances.
*
* @since 1.1.0
*
* @var array
*/
private $models = [];
/**
* The last query that ran, stringified.
*
* @since 1.1.0
*/
public $lastQuery = '';
/**
* Prepares the database class for use.
*
* @since 1.0.0
*
* @global object $wpdb The WordPress database object.
*/
public function __construct( $escape = null ) {
global $wpdb;
$this->db = $wpdb;
$this->prefix = $wpdb->prefix;
$this->escapeOptions = is_null( $escape ) ? self::ESCAPE_STRIP_HTML | self::ESCAPE_QUOTE : $escape;
}
/**
* If this is a clone, lets reset all the data.
*
* @since 1.0.0
*/
public function __clone() {
// We need to reset the result separetely as well since it is not in the default array.
$this->reset( [ 'result' ] );
$this->reset();
}
/**
* Gets all AIO installed tables.
*
* @since 1.0.0
*
* @return array An array of custom AIO tables.
*/
public function getInstalledTables() {
$results = $this->db->get_results( 'SHOW TABLES', 'ARRAY_N' );
return ! empty( $results ) ? wp_list_pluck( $results, 0 ) : [];
}
/**
* Gets all columns from a table.
*
* @since 1.0.0
*
* @param string $table The name of the table to lookup columns for.
* @return array An array of custom AIO tables.
*/
public function getColumns( $table ) {
$installedTables = json_decode( aioseoBrokenLinkChecker()->internalOptions->database->installedTables, true );
$table = $this->prefix . $table;
if ( isset( $installedTables[ $table ] ) ) {
if ( empty( $installedTables[ $table ] ) ) {
$installedTables[ $table ] = $this->db->get_col( 'SHOW COLUMNS FROM `' . $table . '`' );
aioseoBrokenLinkChecker()->internalOptions->database->installedTables = wp_json_encode( $installedTables );
}
return $installedTables[ $table ];
}
return [];
}
/**
* Checks if a table exists.
*
* @since 1.0.0
*
* @param string $table The name of the table.
* @return boolean Whether or not the table exists.
*/
public function tableExists( $table ) {
$table = $this->prefix . $table;
$installedTables = json_decode( aioseoBrokenLinkChecker()->internalOptions->database->installedTables, true ) ?: [];
if ( isset( $installedTables[ $table ] ) ) {
return true;
}
$results = $this->db->get_results( "SHOW TABLES LIKE '" . $table . "'" );
if ( ! empty( $results ) ) {
$installedTables[ $table ] = [];
aioseoBrokenLinkChecker()->internalOptions->database->installedTables = wp_json_encode( $installedTables );
return true;
}
return false;
}
/**
* Checks if a column exists on a given table.
*
* @since 1.0.0
*
* @param string $table The name of the table.
* @param string $column The name of the column.
* @return boolean Whether or not the column exists.
*/
public function columnExists( $table, $column ) {
if ( ! $this->tableExists( $table ) ) {
return false;
}
$columns = $this->getColumns( $table );
if ( ! in_array( $column, $columns, true ) ) {
return false;
}
return true;
}
/**
* Gets the size of a table in bytes.
*
* @since 1.0.0
*
* @param string $table The table to check.
* @return integer The size of the table in bytes.
*/
public function getTableSize( $table ) {
$this->db->query( 'ANALYZE TABLE ' . $this->prefix . $table );
$results = $this->db->get_results( '
SELECT
TABLE_NAME AS `table`,
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH)) AS `size`
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = "' . $this->db->dbname . '"
AND TABLE_NAME = "' . $this->prefix . $table . '"
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;
' );
return empty( $results ) ? 0 : $results[0]->size;
}
/**
* The query string in all its glory.
*
* @since 1.0.0
*
* @return string The actual query string.
*/
public function __toString() {
switch ( strtoupper( $this->statement ) ) {
case 'INSERT':
$insert = 'INSERT ';
if ( $this->ignore ) {
$insert .= 'IGNORE ';
}
$insert .= 'INTO ' . $this->table;
$clauses = [];
$clauses[] = $insert;
$clauses[] = 'SET ' . implode( ', ', $this->set );
if ( ! empty( $this->onDuplicate ) ) {
$clauses[] = 'ON DUPLICATE KEY UPDATE ' . implode( ', ', $this->onDuplicate );
}
break;
case 'REPLACE':
$clauses = [];
$clauses[] = "REPLACE INTO $this->table";
$clauses[] = 'SET ' . implode( ', ', $this->set );
break;
case 'UPDATE':
$clauses = [];
$clauses[] = "UPDATE $this->table";
if ( count( $this->join ) > 0 ) {
foreach ( (array) $this->join as $join ) {
if ( is_array( $join[1] ) ) {
$join_on = []; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
foreach ( (array) $join[1] as $left => $right ) {
$join_on[] = "$this->table.`$left` = `{$join[0]}`.`$right`"; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
}
// phpcs:disable Squiz.NamingConventions.ValidVariableName
$clauses[] = "\t" . ( ( 'LEFT' === $join[2] || 'RIGHT' === $join[2] ) ? $join[2] . ' JOIN ' : 'JOIN ' ) . $join[0] . ' ON ' . implode( ' AND ', $join_on );
// phpcs:enable Squiz.NamingConventions.ValidVariableName
} else {
$clauses[] = "\t" . ( ( 'LEFT' === $join[2] || 'RIGHT' === $join[2] ) ? $join[2] . ' JOIN ' : 'JOIN ' ) . "{$join[0]} ON {$join[1]}";
}
}
}
$clauses[] = 'SET ' . implode( ', ', $this->set );
if ( count( $this->where ) > 0 ) {
$clauses[] = "WHERE 1 = 1 AND\n\t" . implode( "\n\tAND ", $this->where );
}
if ( count( $this->order ) > 0 ) {
$clauses[] = 'ORDER BY ' . implode( ', ', $this->order );
}
if ( $this->limit ) {
$clauses[] = 'LIMIT ' . $this->limit;
}
break;
case 'TRUNCATE':
$clauses = [];
$clauses[] = "TRUNCATE TABLE $this->table";
break;
case 'DELETE':
$clauses = [];
$clauses[] = "DELETE FROM $this->table";
if ( count( $this->where ) > 0 ) {
$clauses[] = "WHERE 1 = 1 AND\n\t" . implode( "\n\tAND ", $this->where );
}
if ( count( $this->order ) > 0 ) {
$clauses[] = 'ORDER BY ' . implode( ', ', $this->order );
}
if ( $this->limit ) {
$clauses[] = 'LIMIT ' . $this->limit;
}
break;
case 'SELECT':
case 'SELECT DISTINCT':
default:
// Select fields.
$clauses = [];
$distinct = ( $this->distinct || stripos( $this->statement, 'DISTINCT' ) !== false ) ? 'DISTINCT ' : '';
$select = ( count( $this->select ) > 0 ) ? implode( ",\n\t", $this->select ) : '*';
$clauses[] = "SELECT {$distinct}\n\t{$select}";
// Select table.
$clauses[] = "FROM $this->table";
// Select joins.
if ( ! empty( $this->join ) && count( $this->join ) > 0 ) {
foreach ( (array) $this->join as $join ) {
if ( is_array( $join[1] ) ) {
$join_on = []; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
foreach ( (array) $join[1] as $left => $right ) {
$join_on[] = "$this->table.`$left` = `{$join[0]}`.`$right`"; // phpcs:ignore Squiz.NamingConventions.ValidVariableName
}
// phpcs:disable Squiz.NamingConventions.ValidVariableName
$clauses[] = "\t" . ( ( 'LEFT' === $join[2] || 'RIGHT' === $join[2] ) ? $join[2] . ' JOIN ' : 'JOIN ' ) . $join[0] . ' ON ' . implode( ' AND ', $join_on );
// phpcs:enable Squiz.NamingConventions.ValidVariableName
} else {
$clauses[] = "\t" . ( ( 'LEFT' === $join[2] || 'RIGHT' === $join[2] ) ? $join[2] . ' JOIN ' : 'JOIN ' ) . "{$join[0]} ON {$join[1]}";
}
}
}
// Select conditions.
if ( count( $this->where ) > 0 ) {
$clauses[] = "WHERE 1 = 1 AND\n\t" . implode( "\n\tAND ", $this->where );
}
// Union queries.
if ( count( $this->union ) > 0 ) {
foreach ( $this->union as $union ) {
$keyword = ( $union[1] ) ? 'UNION' : 'UNION ALL';
$clauses[] = "\n$keyword\n\n$union[0]";
}
$clauses[] = '';
}
// Select groups.
if ( count( $this->group ) > 0 ) {
$clauses[] = 'GROUP BY ' . implode( ', ', $this->escapeColNames( $this->group ) );
}
// Select order.
if ( count( $this->order ) > 0 ) {
$orderFragments = [];
foreach ( $this->escapeColNames( $this->order ) as $col ) {
$orderFragments[] = ( preg_match( '/ (ASC|DESC|RAND\(\))$/i', $col ) ) ? $col : "$col $this->orderDirection";
}
$clauses[] = 'ORDER BY ' . implode( ', ', $orderFragments );
}
// Select limit.
if ( $this->limit ) {
$clauses[] = 'LIMIT ' . $this->limit;
}
break;
}
// @HACK for wpdb::prepare.
$clauses[] = '/* %d = %d */';
$this->query = str_replace( '%%d = %%d', '%d = %d', str_replace( '%', '%%', implode( "\n", $clauses ) ) );
$this->lastQuery = $this->query;
return $this->query;
}
/**
* Shortcut method to return the query string.
*
* @since 1.0.0
*
* @return string The query string.
*/
public function query() {
return $this->__toString();
}
/**
* Start a new Database Query.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @param string $statement The MySQL statement for the query.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function start( $table = null, $includesPrefix = false, $statement = 'SELECT' ) {
// Always reset everything when starting a new query.
$this->reset();
$this->table = $includesPrefix ? $table : $this->prefix . $table;
$this->statement = $statement;
return $this;
}
/**
* Shortcut method for start with INSERT as the statement.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function insert( $table = null, $includesPrefix = false ) {
return $this->start( $table, $includesPrefix, 'INSERT' );
}
/**
* Shortcut method for start with INSERT IGNORE as the statement.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function insertIgnore( $table = null, $includesPrefix = false ) {
$this->ignore = true;
return $this->start( $table, $includesPrefix, 'INSERT' );
}
/**
* Shortcut method for start with UPDATE as the statement.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function update( $table = null, $includesPrefix = false ) {
return $this->start( $table, $includesPrefix, 'UPDATE' );
}
/**
* Shortcut method for start with REPLACE as the statement.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function replace( $table = null, $includesPrefix = false ) {
return $this->start( $table, $includesPrefix, 'REPLACE' );
}
/**
* Shortcut method for start with TRUNCATE as the statement.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function truncate( $table = null, $includesPrefix = false ) {
return $this->start( $table, $includesPrefix, 'TRUNCATE' );
}
/**
* Shortcut method for start with DELETE as the statement.
*
* @since 1.0.0
*
* @param string $table The name of the table without the WordPress prefix unless includes_prefix is true.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can then be method chained for building the query.
*/
public function delete( $table = null, $includesPrefix = false ) {
return $this->start( $table, $includesPrefix, 'DELETE' );
}
/**
* Adds a SELECT clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function select() {
$args = (array) func_get_args();
if ( count( $args ) === 1 && is_array( $args[0] ) ) {
$args = $args[0];
}
$this->select = array_merge( $this->select, $this->escapeColNames( $args ) );
return $this;
}
/**
* Adds a WHERE clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function where() {
$criteria = $this->prepArgs( func_get_args() );
foreach ( (array) $criteria as $field => $value ) {
if ( ! preg_match( '/[\(\)<=>!]+/', $field ) && false === stripos( $field, ' IS ' ) ) {
$operator = ( is_null( $value ) ) ? 'IS' : '=';
$escaped = $this->escapeColNames( $field );
$field = array_pop( $escaped ) . ' ' . $operator;
}
if ( is_null( $value ) && false !== stripos( $field, ' IS ' ) ) {
// WHERE `field` IS NOT NULL.
$this->where[] = "$field NULL";
} elseif ( is_null( $value ) ) {
// WHERE `field` IS NULL.
$this->where[] = "$field NULL";
} elseif ( is_array( $value ) ) {
$wheres = [];
foreach ( (array) $value as $val ) {
$wheres[] = sprintf( "$field %s", $this->escape( $val, $this->getEscapeOptions() | self::ESCAPE_QUOTE ) );
}
$this->where[] = '(' . implode( ' OR ', $wheres ) . ')';
} else {
$this->where[] = sprintf( "$field %s", $this->escape( $value, $this->getEscapeOptions() | self::ESCAPE_QUOTE ) );
}
}
return $this;
}
/**
* Adds a complex WHERE clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function whereRaw() {
$criteria = $this->prepArgs( func_get_args() );
foreach ( (array) $criteria as $clause ) {
$this->where[] = $clause;
}
return $this;
}
/**
* Adds a WHERE clause with all arguments sent separated by OR instead of AND inside a subclause.
* @example [ 'a' => 1, 'b' => 2 ] becomes "AND (a = 1 OR b = 2)"
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function whereOr() {
$criteria = $this->prepArgs( func_get_args() );
$or = [];
foreach ( (array) $criteria as $field => $value ) {
if ( ! preg_match( '/[\(\)<=>!]+/', $field ) && false === stripos( $field, ' IS ' ) ) {
$operator = ( is_null( $value ) ) ? 'IS' : '=';
$field = $this->escapeColNames( $field );
$field = array_pop( $field ) . ' ' . $operator;
}
if ( is_null( $value ) && false !== stripos( $field, ' IS ' ) ) {
// WHERE `field` IS NOT NULL.
$or[] = "$field NULL";
} elseif ( is_null( $value ) ) {
// WHERE `field` IS NULL.
$or[] = "$field NULL";
} else {
$or[] = sprintf( "$field %s", $this->escape( $value, $this->getEscapeOptions() | self::ESCAPE_QUOTE ) );
}
}
// Create our subclause, and add it to the WHERE array.
$this->where[] = '(' . implode( ' OR ', $or ) . ')';
return $this;
}
/**
* Adds a WHERE IN() clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function whereIn() {
$criteria = $this->prepArgs( func_get_args() );
foreach ( (array) $criteria as $field => $values ) {
if ( ! is_array( $values ) ) {
$values = [ $values ];
} elseif ( count( $values ) === 0 ) {
continue;
}
foreach ( $values as &$value ) {
// Note: We can no longer check for `is_numeric` because a value like `61021e6242255` returns true and breaks the query.
if ( is_integer( $value ) || is_float( $value ) ) {
// No change.
} elseif ( is_null( $value ) || false !== stristr( $value, 'NULL' ) ) {
// Change to a true NULL value.
$value = null;
} else {
$value = sprintf( '%s', $this->escape( $value, $this->getEscapeOptions() | self::ESCAPE_QUOTE ) );
}
}
$values = implode( ',', $values );
$this->whereRaw( "$field IN($values)" );
}
return $this;
}
/**
* Adds a WHERE NOT IN() clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function whereNotIn() {
$criteria = $this->prepArgs( func_get_args() );
foreach ( (array) $criteria as $field => $values ) {
if ( ! is_array( $values ) ) {
$values = [ $values ];
} elseif ( count( $values ) === 0 ) {
continue;
}
foreach ( $values as &$value ) {
if ( is_numeric( $value ) ) {
// No change.
} elseif ( is_null( $value ) || false !== stristr( $value, 'NULL' ) ) {
// Change to a true NULL value.
$value = null;
} else {
$value = sprintf( '%s', $this->escape( $value, $this->getEscapeOptions() | self::ESCAPE_QUOTE ) );
}
}
$values = implode( ',', $values );
$this->whereRaw( "$field NOT IN($values)" );
}
return $this;
}
/**
* Adds a LEFT JOIN clause.
*
* @since 1.0.0
*
* @param string $table The name of the table to join to this query.
* @param string|array $conditions The conditions of the join clause.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function leftJoin( $table, $conditions, $includesPrefix = false ) {
return $this->join( $table, $conditions, 'LEFT', $includesPrefix );
}
/**
* Adds a JOIN clause.
*
* @since 1.0.0
*
* @param string $table The name of the table to join to this query.
* @param string|array $conditions The conditions of the join clause.
* @param string $direction This can take 'LEFT' or 'RIGHT' as arguments.
* @param boolean $includesPrefix This determines if the table name includes the WordPress prefix or not.
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function join( $table, $conditions, $direction = '', $includesPrefix = false ) {
$this->join[] = [ $includesPrefix ? $table : $this->prefix . $table, $conditions, $direction ];
return $this;
}
/**
* Add a UNION query.
*
* @since 1.0.0
*
* @param Database|string $query The query (Database object or query string) to be joined with.
* @param Bool $distinct Set whether this union should be distinct or not.
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function union( $query, $distinct = true ) {
$this->union[] = [ $query, $distinct ];
return $this;
}
/**
* Adds a GROUP BY clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function groupBy() {
$args = (array) func_get_args();
if ( count( $args ) === 1 && is_array( $args[0] ) ) {
$args = $args[0];
}
$this->group = array_merge( $this->group, $args );
return $this;
}
/**
* Adds a ORDER BY clause.
*
* @since 1.0.0
* @version 1.2.4 Hardened against SQL injection.
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function orderBy() {
// Normalize arguments.
$args = (array) func_get_args();
if ( count( $args ) === 1 && is_array( $args[0] ) ) {
$args = $args[0];
}
$orderBy = [];
// Separate commas to account for multiple orders.
foreach ( $args as $argComma ) {
$orderBy = array_map( 'trim', array_merge( $orderBy, explode( ',', $argComma ) ) );
}
// Validate and sanitize column names and sort directions.]
$sanitizedOrderBy = [];
foreach ( $orderBy as $ordBy ) {
$parts = explode( ' ', $ordBy );
$column = str_replace( '`', '', $parts[0] ); // Strip existing ticks first.
$column = preg_replace( '/[^a-zA-Z0-9_.]/', '', $column ); // Strip invalid characters from the column name.
$column = $this->escapeColNames( $column )[0];
$direction = isset( $parts[1] ) ? strtoupper( $parts[1] ) : 'ASC';
// Validate the order direction.
if ( ! in_array( $direction, [ 'ASC', 'DESC' ], true ) ) {
$direction = 'ASC';
}
$sanitizedOrderBy[] = "$column $direction";
}
if ( ! empty( $sanitizedOrderBy ) ) {
if ( ! empty( $args[0] ) && true !== $args[0] ) {
$this->order = array_merge( $this->order, $sanitizedOrderBy );
} else {
// This allows for overwriting a preexisting order-by setting.
array_shift( $sanitizedOrderBy );
$this->order = $sanitizedOrderBy;
}
}
return $this;
}
/**
* Adds a raw ORDER BY clause.
*
* @since 1.2.4
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function orderByRaw() {
$args = (array) func_get_args();
if ( count( $args ) === 1 && is_array( $args[0] ) ) {
$args = $args[0];
}
$this->order = array_merge( $this->order, $args );
return $this;
}
/**
* Sets the sort direction for ORDER BY clauses.
*
* @since 1.0.0
*
* @param string $direction This sets the direction of the order by clause, default is 'ASC'.
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function orderDirection( $direction = 'ASC' ) {
$this->orderDirection = $direction;
return $this;
}
/**
* Adds a LIMIT clause.
*
* @since 1.0.0
*
* @param int $limit The limit for the limit clause.
* @param int $offset The offset for the limit clause.
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function limit( $limit, $offset = -1 ) {
if ( ! is_numeric( $limit ) || $limit <= 0 ) {
return $this;
}
if ( ! is_numeric( $offset ) ) {
$offset = -1;
}
$this->limit = ( -1 === $offset )
? intval( $limit )
: intval( $offset ) . ', ' . intval( $limit );
return $this;
}
/**
* Converts associative arrays to a SET argument.
*
* @since 1.0.0
*
* @param array $args The arguments.
* @return array $preparedSet The prepared arguments.
*/
private function prepareSet( $args ) {
$args = $this->prepArgs( $args );
$preparedSet = [];
foreach ( (array) $args as $field => $value ) {
if ( is_null( $value ) ) {
$preparedSet[] = "`$field` = NULL";
} elseif ( is_array( $value ) ) {
throw new \Exception( 'Cannot save an unserialized array in the database. Data passed was: ' . wp_json_encode( $value ) );
} elseif ( is_object( $value ) ) {
throw new \Exception( 'Cannot save an unserialized object in the database. Data passed was: ' . esc_html( $value ) );
} else {
$preparedSet[] = sprintf( "`$field` = %s", $this->escape( $value, $this->getEscapeOptions() | self::ESCAPE_QUOTE ) );
}
}
return $preparedSet;
}
/**
* Adds a SET clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function set() {
$this->set = array_merge( $this->set, $this->prepareSet( func_get_args() ) );
return $this;
}
/**
* Adds an ON DUPLICATE clause.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function onDuplicate() {
$this->onDuplicate = array_merge( $this->onDuplicate, $this->prepareSet( func_get_args() ) );
return $this;
}
/**
* Set the output for the query.
*
* @since 1.0.0
*
* @param string $output This can be one of the following: ARRAY_A | ARRAY_N | OBJECT | OBJECT_K.
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function output( $output ) {
$this->output = $output;
return $this;
}
/**
* Reset the cache so we make sure the query gets to the DB.
*
* @since 1.0.0
*
* @return Database Returns the Database class which can be method chained for more query building.
*/
public function resetCache() {
$this->shouldResetCache = true;
return $this;
}
/**
* Run this query.
*
* @since 1.0.0
*
* @param boolean $reset Whether to reset the results/query.
* @param string $return Determine which method to call on the $wpdb object
* @param array $params Optional extra parameters to pass to the db method call
* @return Database Database query results.
*/
public function run( $reset = true, $return = 'results', $params = [] ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( ! in_array( $return, [ 'results', 'col', 'var' ], true ) ) {
$return = 'results';
}
$prepare = $this->db->prepare( $this->query(), 1, 1 );
$queryHash = sha1( $this->query() );
$cacheTableName = $this->getCacheTableName();
// Pull the result from the in-memory cache if everything checks out.
if (
! $this->shouldResetCache &&
isset( $this->cache[ $cacheTableName ][ $queryHash ][ $return ] ) &&
empty( $this->join )
) {
$this->result = $this->cache[ $cacheTableName ][ $queryHash ][ $return ];
return $this;
}
switch ( $return ) {
case 'col':
$this->result = $this->db->get_col( $prepare );
break;
case 'var':
$this->result = $this->db->get_var( $prepare );
break;
default:
$this->result = $this->db->get_results( $prepare, $this->output );
}
if ( $reset ) {
$this->reset();
}
$this->cache[ $cacheTableName ][ $queryHash ][ $return ] = $this->result;
// Reset the cache trigger for the next run.
$this->shouldResetCache = false;
return $this;
}
/**
* Inject a count select statement and return the result.
*
* @since 1.0.0
*
* @param string $countColumn The column to count with. Defaults to '*' all.
* @return int The count total.
*/
public function count( $countColumn = '*' ) {
$usingGroup = ! empty( $this->group );
$results = $this->select( 'count(' . $countColumn . ') as count' )
->run()
->result();
return 1 === $this->numRows() && ! $usingGroup ? (int) $results[0]->count : $this->numRows();
}
/**
* Returns the query results based on the output.
*
* @since 1.0.0
*
* @return mixed This could be an array or an object based on the original output method.
*/
public function result() {
return $this->result;
}
/**
* Return a model model from a row.
*
* @since 1.0.0
*
* @param string $class The class to call.
* @return object The class object.
*/
public function model( $class ) {
$result = $this->result();
return ! empty( $result ) ? ( is_array( $result ) ? new $class( (array) current( $result ) ) : $result ) : new $class();
}
/**
* Return an array of model models from the result
*
* @since 1.0.0
*
* @param string $class The class to call.
* @param string $id The id of the index to use.
* @param bool $toJson Whether to convert to json.
* @return array An array of class models.
*/
public function models( $class, $id = null, $toJson = false ) {
if ( empty( $this->models ) ) {
$i = 0;
$models = [];
foreach ( $this->result() as $row ) {
$var = ( null === $id ) ? $row : $row[ $id ];
$class = new $class( $var );
// Lets add the class to the array using the class ID.
$models[ $class->id ] = $toJson ? $class->jsonSerialize() : $class;
$i++;
}
$this->models = $models;
}
return $this->models;
}
/**
* Returns the last error reported by MySQL.
*
* @since 1.0.0
*
* @return string The last error.
*/
public function lastError() {
return $this->db->last_error;
}
/**
* Return the $wpdb insert_id from the last query.
*
* @since 1.0.0
*
* @return integer The id of the most recent INSERT query.
*/
public function insertId() {
return $this->db->insert_id;
}
/**
* Return the $wpdb rows_affected from the last query.
*
* @since 1.0.0
*
* @return integer The number of rows affected.
*/
public function rowsAffected() {
return $this->db->rows_affected;
}
/**
* Return the $wpdb num_rows from the last query.
*
* @since 1.0.0
*
* @return integer The count for the number of rows in the last query.
*/
public function numRows() {
return $this->db->num_rows;
}
/**
* Check if the last query had any rows.
*
* @since 1.0.0
*
* @return bool Whether there were any rows retrived by the last query.
*/
public function nullSet() {
return ( $this->numRows() < 1 );
}
/**
* This will start a MySQL transaction. Be sure to commit or rollback!
*
* @since 1.0.0
*/
public function startTransaction() {
$this->db->query( 'START TRANSACTION' );
}
/**
* This will commit a MySQL transaction. Used in conjunction with startTransaction.
*
* @since 1.0.0
*/
public function commit() {
$this->db->query( 'COMMIT' );
}
/**
* This will rollback a MySQL transaction. Used in conjunction with startTransaction.
*
* @since 1.0.0
*/
public function rollback() {
$this->db->query( 'ROLLBACK' );
}
/**
* Fast way to execute queries.
*
* @since 1.0.0
*
* @param string $sql The sql query to execute.
* @return mixed Could be an array or object depending on the result set.
*/
public function execute( $sql, $results = false ) {
$this->lastQuery = $sql;
if ( $results ) {
$this->result = $this->db->get_results( $sql );
return $this;
}
return $this->db->query( $sql );
}
/**
* Escape a value for safe use in SQL queries.
*
* @param string $value The value to be escaped.
* @param boolean $options Escape options.
* @return string The escaped SQL value.
*/
public function escape( $value, $options = null ) {
if ( is_array( $value ) ) {
foreach ( $value as &$val ) {
$val = $this->escape( $val, $options );
}
return $value;
} else {
$options = ( is_null( $options ) ) ? $this->getEscapeOptions() : $options;
if ( ( $options & self::ESCAPE_STRIP_HTML ) !== 0 && isset( $this->stripTags ) && true === $this->stripTags ) {
$value = wp_strip_all_tags( $value );
}
if (
( ( $options & self::ESCAPE_FORCE ) !== 0 || php_sapi_name() === 'cli' ) ||
( ( $options & self::ESCAPE_QUOTE ) !== 0 && ! is_integer( $value ) )
) {
$value = esc_sql( $value );
if ( ! is_integer( $value ) ) {
$value = "'$value'";
}
}
return $value;
}
}
/**
* Get the current escape options.
*
* @since 1.0.0
*
* @return integer The current escape options.
*/
public function getEscapeOptions() {
return $this->escapeOptions;
}
/**
* Set the current escape options.
*
* @since 1.0.0
*
* @param integer $options
*/
public function setEscapeOptions( $options ) {
$this->escapeOptions = $options;
}
/**
* Backtick-escapes an array of column and/or table names.
*
* @since 1.0.0
*
* @param array $cols An array of column names to be escaped.
* @return array An array of escaped column names.
*/
private function escapeColNames( $cols ) {
if ( ! is_array( $cols ) ) {
$cols = [ $cols ];
}
foreach ( $cols as &$col ) {
if ( false === stripos( $col, '(' ) && false === stripos( $col, ' ' ) && false === stripos( $col, '*' ) ) {
if ( stripos( $col, '.' ) ) {
list( $table, $c ) = explode( '.', $col );
$col = "`$table`.`$c`";
continue;
}
$col = "`$col`";
}
}
return $cols;
}
/**
* Gets a variable list of function arguments and reformats them as needed for many of the functions of this class.
*
* @since 1.0.0
*
* @param mixed $values This could be anything, but if used properly its usually a string or an array.
* @return array If the preparation is correct it will return an array of arguments.
*/
private function prepArgs( $values ) {
$values = (array) $values;
if ( ! is_array( $values[0] ) && count( $values ) === 2 ) {
$values = [ $values[0] => $values[1] ];
} elseif ( is_array( $values[0] ) && count( $values ) === 1 ) {
$values = $values[0];
}
return $values;
}
/**
* Resets all the variables that make up the query.
*
* @since 1.0.0
*
* @param array $what Set which items you want to reset, all are selected by default.
* @return Database Returns the Database object.
*/
public function reset(
$what = [
'table',
'statement',
'limit',
'group',
'order',
'select',
'set',
'onDuplicate',
'ignore',
'where',
'union',
'distinct',
'orderDirection',
'query',
'output',
'stripTags',
'models',
'join'
]
) {
// If we are not running a select query, let's bust the cache for this table.
$selectStatements = [ 'SELECT', 'SELECT DISTINCT' ];
if (
! empty( $this->statement ) &&
! in_array( $this->statement, $selectStatements, true )
) {
$this->bustCache( $this->getCacheTableName() );
}
foreach ( (array) $what as $var ) {
switch ( $var ) {
case 'group':
case 'order':
case 'select':
case 'set':
case 'onDuplicate':
case 'where':
case 'union':
case 'join':
$this->$var = [];
break;
case 'orderDirection':
$this->$var = 'ASC';
break;
case 'ignore':
case 'stripTags':
$this->$var = false;
break;
case 'output':
$this->$var = 'OBJECT';
break;
default:
if ( isset( $this->$var ) ) {
$this->$var = null;
}
break;
}
}
return $this;
}
/**
* Get the current value of one or more query properties. If only one property is specified, returns the value;
* if an array of values is specified, then returns an array of values.
*
* @since 1.0.0
*
* @param string|array $what You can pass in an array of options to retrieve. By default it selects all if them.
* @return string|array Returns the value of whichever variables are passed in.
*/
public function getQueryProperty(
$what = [
'table',
'statement',
'limit',
'group',
'order',
'select',
'set',
'onDuplicate',
'where',
'union',
'distinct',
'orderDirection',
'query',
'output',
'result'
]
) {
if ( is_array( $what ) ) {
$return = [];
foreach ( (array) $what as $which ) {
$return[ $which ] = $this->$which;
}
return $return;
} else {
return $this->$what;
}
}
/**
* Get a table name for the cache key.
*
* @since 1.0.0
*
* @param string $cacheTableName The table name to check against.
* @return string The cache key table name.
*/
private function getCacheTableName( $cacheTableName = null ) {
$cacheTableName = empty( $cacheTableName ) ? $this->table : $cacheTableName;
foreach ( $this->customTables as $tableName ) {
if ( false !== stripos( $cacheTableName, $this->prefix . $tableName ) ) {
$cacheTableName = $tableName;
break;
}
}
return $cacheTableName;
}
/**
* Busts the cache for the given table name.
*
* @since 1.0.0
*
* @param string|null $tableName The table name.
* @return void
*/
public function bustCache( $tableName = null ) {
if ( ! $tableName ) {
// Bust all the cache.
$this->cache = [];
return;
}
unset( $this->cache[ $tableName ] );
}
/**
* In order to not have a conflict, we need to return a clone.
*
* @since 1.0.0
*
* @return Database The cloned Database object.
*/
public function noConflict() {
return clone $this;
}
} Filesystem.php 0000644 00000013735 15154027146 0007417 0 ustar 00 <?php
// phpcs:disable WordPress.WP.AlternativeFunctions
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Interface for the filesystem.
*
* @since 1.0.0
*/
class Filesystem {
/**
* Holds the WP filesystem instance.
*
* @since 1.0.0
*
* @var \WP_Filesystem_Base
*/
public $fs = null;
/**
* Core class instance.
*
* @since 1.1.0
*
* @var Core
*/
public $core = null;
/**
* Class constructor.
*
* @since 1.0.0
*
* @param Core $core The Core class.
* @param array $args Optional arguments needed to construct the class with.
*/
public function __construct( $core, $args = [] ) {
$this->core = $core;
$this->init( $args );
}
/**
* Initialize the filesystem.
*
* @since 1.0.0
*
* @param array $args List of arguments for the WP_Filesystem class.
* @return void
*/
public function init( $args = [] ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem( $args );
// phpcs:disable Squiz.NamingConventions.ValidVariableName
global $wp_filesystem;
if ( is_object( $wp_filesystem ) ) {
$this->fs = $wp_filesystem;
}
// phpcs:enable Squiz.NamingConventions.ValidVariableName
}
/**
* Wrapper method to check if a file exists.
*
* @since 1.0.0
*
* @param string $filename The filename to check if it exists.
* @return bool Returns true if the file or dir specified exists; false otherwise.
*/
public function exists( $filename ) {
if ( ! $this->isWpfsValid() ) {
return @file_exists( $filename );
}
return $this->fs->exists( $filename );
}
/**
* Retrieve the contents of a file.
*
* @since 1.0.0
*
* @param string $filename The filename to get the contents for.
* @return string|bool The function returns the read data or false on failure.
*/
public function getContents( $filename ) {
if ( ! $this->exists( $filename ) ) {
return false;
}
if ( ! $this->isWpfsValid() ) {
return @file_get_contents( $filename );
}
return $this->fs->get_contents( $filename );
}
/**
* Reads entire file into an array.
*
* @since 1.0.0
*
* @param string $file Path to the file.
* @return array|bool File contents in an array on success, false on failure.
*/
public function getContentsArray( $file ) {
if ( ! $this->exists( $file ) ) {
return false;
}
if ( ! $this->isWpfsValid() ) {
return @file( $file );
}
return $this->fs->get_contents_array( $file );
}
/**
* Sets the access and modification times of a file.
* Note: If $file doesn't exist, it will be created.
*
* @since 1.0.0
*
* @param string $file Path to file.
* @param int $time Optional. Modified time to set for file. Default 0.
* @param int $atime Optional. Access time to set for file. Default 0.
* @return bool True on success, false on failure.
*/
public function touch( $file, $time = 0, $atime = 0 ) {
if ( 0 === $time ) {
$time = time();
}
if ( 0 === $atime ) {
$atime = time();
}
if ( ! $this->isWpfsValid() ) {
return @touch( $file, $time, $atime );
}
return $this->fs->touch( $file, $time, $atime );
}
/**
* Writes a string to a file.
*
* @since 1.0.0
*
* @param string $file Remote path to the file where to write the data.
* @param string $contents The data to write.
* @param int|false $mode Optional. The file permissions as octal number, usually 0644. Default false.
* @return int|bool True on success, false on failure.
*/
public function putContents( $file, $contents, $mode = false ) {
if ( ! $this->isWpfsValid() ) {
return @file_put_contents( $file, $contents );
}
return $this->fs->put_contents( $file, $contents, $mode );
}
/**
* Checks if a file or dir is writable.
*
* @since 1.0.0
*
* @param string $file Path to file or dir.
* @return bool Whether $file is writable.
*/
public function isWritable( $file ) {
if ( ! $this->isWpfsValid() ) {
return @is_writable( $file );
}
return $this->fs->is_writable( $file );
}
/**
* Checks if a file is readable.
*
* @since 1.0.0
*
* @param string $file Path to file.
* @return bool Whether $file is readable.
*/
public function isReadable( $file ) {
if ( ! $this->isWpfsValid() ) {
return @is_readable( $file );
}
return $this->fs->is_readable( $file );
}
/**
* Gets the file size (in bytes).
*
* @since 1.0.0
*
* @param string $file Path to file.
* @return int|bool Size of the file in bytes on success, false on failure.
*/
public function size( $file ) {
if ( ! $this->isWpfsValid() ) {
return @filesize( $file );
}
return $this->fs->size( $file );
}
/**
* Checks if resource is a file.
*
* @since 1.0.0
*
* @param string $file File path.
* @return bool Whether $file is a file.
*/
public function isFile( $file ) {
if ( ! $this->isWpfsValid() ) {
return @is_file( $file );
}
return $this->fs->is_file( $file );
}
/**
* Checks if resource is a directory.
*
* @since 1.0.0
*
* @param string $path Directory path.
* @return bool Whether $path is a directory.
*/
public function isDir( $path ) {
if ( ! $this->isWpfsValid() ) {
return @is_dir( $path );
}
return $this->fs->is_dir( $path );
}
/**
* A simple check to ensure that the WP_Filesystem is valid.
*
* @since 1.0.0
*
* @return bool True if valid, false if not.
*/
public function isWpfsValid() {
if (
! is_a( $this->fs, 'WP_Filesystem_Base' ) ||
(
// Errors is a WP_Error object.
! empty( $this->fs->errors ) &&
// We check if the errors array is empty for compatibility with WP < 5.1.
! empty( $this->fs->errors->errors )
)
) {
return false;
}
return true;
}
/**
* In order to prevent conflicts, we need to return a clone.
*
* @since 1.0.0
*
* @return Filesystem The cloned Filesystem object.
*/
public function noConflict() {
return clone $this;
}
} NetworkCache.php 0000644 00000005314 15154027146 0007642 0 ustar 00 <?php
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles our network cache.
*
* @since 1.0.0
*/
class NetworkCache extends Cache {
/**
* Returns the cache value for a key if it exists and is not expired.
*
* @since 1.0.0
*
* @param string $key The cache key name. Use a '%' for a like query.
* @return mixed The value or null if the cache does not exist.
*/
public function get( $key ) {
if ( ! is_multisite() ) {
return parent::get( $key );
}
aioseoBrokenLinkChecker()->helpers->switchToBlog( aioseoBrokenLinkChecker()->helpers->getNetworkId() );
$value = parent::get( $key );
aioseoBrokenLinkChecker()->helpers->restoreCurrentBlog();
return $value;
}
/**
* Updates the given cache or creates it if it doesn't exist.
*
* @since 1.0.0
*
* @param string $key The cache key name.
* @param mixed $value The value.
* @param int $expiration The expiration time in seconds. Defaults to 24 hours. 0 to no expiration.
* @return void
*/
public function update( $key, $value, $expiration = DAY_IN_SECONDS ) {
if ( ! is_multisite() ) {
parent::update( $key, $value, $expiration );
return;
}
aioseoBrokenLinkChecker()->helpers->switchToBlog( aioseoBrokenLinkChecker()->helpers->getNetworkId() );
parent::update( $key, $value, $expiration );
aioseoBrokenLinkChecker()->helpers->restoreCurrentBlog();
}
/**
* Deletes the given cache key.
*
* @since 1.0.0
*
* @param string $key The cache key.
* @return void
*/
public function delete( $key ) {
if ( ! is_multisite() ) {
parent::delete( $key );
return;
}
aioseoBrokenLinkChecker()->helpers->switchToBlog( aioseoBrokenLinkChecker()->helpers->getNetworkId() );
parent::delete( $key );
aioseoBrokenLinkChecker()->helpers->restoreCurrentBlog();
}
/**
* Clears all of our cache.
*
* @since 1.0.0
*
* @return void
*/
public function clear() {
if ( ! is_multisite() ) {
parent::clear();
return;
}
aioseoBrokenLinkChecker()->helpers->switchToBlog( aioseoBrokenLinkChecker()->helpers->getNetworkId() );
parent::clear();
aioseoBrokenLinkChecker()->helpers->restoreCurrentBlog();
}
/**
* Clears all of our cache under a certain prefix.
*
* @since 1.0.0
*
* @param string $prefix A prefix to clear or empty to clear everything.
* @return void
*/
public function clearPrefix( $prefix ) {
if ( ! is_multisite() ) {
parent::clearPrefix( $prefix );
return;
}
aioseoBrokenLinkChecker()->helpers->switchToBlog( aioseoBrokenLinkChecker()->helpers->getNetworkId() );
parent::clearPrefix( $prefix );
aioseoBrokenLinkChecker()->helpers->restoreCurrentBlog();
}
} Uninstall.php 0000644 00000004675 15154027146 0007247 0 ustar 00 <?php
namespace AIOSEO\BrokenLinkChecker\Core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\BrokenLinkChecker\Utils;
/**
* Handles plugin deinstallation.
*
* @since 1.0.0
*/
class Uninstall {
/**
* Removes all our tables and options.
*
* @since 1.0.0
*
* @param bool $force Whether we should ignore the uninstall option or not. We ignore it when we reset all data via the Debug Panel.
* @return void
*/
public function dropData( $force = false ) {
// Confirm that user has decided to remove all data, otherwise stop.
if (
! $force &&
( ! aioseoBrokenLinkChecker()->options->advanced->enable || ! aioseoBrokenLinkChecker()->options->advanced->uninstall )
) {
return;
}
// Delete all our custom tables.
global $wpdb;
foreach ( $this->getDbTables() as $tableName ) {
$wpdb->query( 'DROP TABLE IF EXISTS ' . $tableName ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
// Delete all the plugin settings.
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'aioseo\_blc\_%'" );
// Remove any transients we've left behind.
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_aioseo\_blc\_%'" );
// Delete all entries from the action scheduler table.
$wpdb->query( "DELETE FROM {$wpdb->prefix}actionscheduler_actions WHERE hook LIKE 'aioseo\_blc\_%'" );
$wpdb->query( "DELETE FROM {$wpdb->prefix}actionscheduler_groups WHERE slug = 'aioseo\_blc'" );
// Delete all our custom capabilities.
$this->uninstallCapabilities();
}
/**
* Returns all the DB tables with their prefix.
*
* @since 1.0.0
*
* @return array List of tables.
*/
private function getDbTables() {
global $wpdb;
$tables = [];
foreach ( aioseoBrokenLinkChecker()->core->db->customTables as $tableName ) {
$tables[] = $wpdb->prefix . $tableName;
}
return $tables;
}
/**
* Removes all our custom capabilities.
*
* @since 1.2.4
*
* @return void
*/
private function uninstallCapabilities() {
$access = new Utils\Access();
$customCapabilities = $access->getCapabilityList() ?? [];
$roles = aioseoBrokenLinkChecker()->helpers->getUserRoles();
// Loop through roles and remove custom capabilities.
foreach ( $roles as $roleName => $roleInfo ) {
$role = get_role( $roleName );
if ( $role ) {
foreach ( $customCapabilities as $capability ) {
$role->remove_cap( $capability );
}
}
}
}
}