Upgrade to 3.5.5

This commit is contained in:
Bastian Allgeier
2021-05-11 11:55:32 +02:00
parent de3560f3d6
commit efeff45192
146 changed files with 2008 additions and 1075 deletions

View File

@@ -69,7 +69,10 @@ class SimpleImage {
* Destroys the image resource.
*/
public function __destruct() {
if($this->image !== null && is_resource($this->image) && get_resource_type($this->image) === 'gd') {
//Check for a valid GDimage instance
$type_check = (gettype($this->image) == "object" && get_class($this->image) == "GdImage");
if($this->image !== null && is_resource($this->image) && $type_check) {
imagedestroy($this->image);
}
}
@@ -128,7 +131,7 @@ class SimpleImage {
fclose($handle);
// Get image info
$info = getimagesize($file);
$info = @getimagesize($file);
if($info === false) {
throw new \Exception("Invalid image file: $file", self::ERR_INVALID_IMAGE);
}
@@ -587,13 +590,27 @@ class SimpleImage {
$y1 = self::keepWithin($y1, 0, $this->getHeight());
$y2 = self::keepWithin($y2, 0, $this->getHeight());
// Avoid using native imagecrop() because of a bug with PNG transparency
$dstW = abs($x2 - $x1);
$dstH = abs($y2 - $y1);
$newImage = imagecreatetruecolor($dstW, $dstH);
$transparentColor = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
imagecolortransparent($newImage, $transparentColor);
imagefill($newImage, 0, 0, $transparentColor);
// Crop it
$this->image = imagecrop($this->image, [
'x' => min($x1, $x2),
'y' => min($y1, $y2),
'width' => abs($x2 - $x1),
'height' => abs($y2 - $y1)
]);
imagecopyresampled(
$newImage,
$this->image,
0, 0, min($x1, $x2), min($y1, $y2),
$dstW,
$dstH,
$dstW,
$dstH
);
// Swap out the new image
$this->image = $newImage;
return $this;
}
@@ -708,10 +725,10 @@ class SimpleImage {
* @param float $opacity The opacity level of the overlay 0-1 (default 1).
* @param integer $xOffset Horizontal offset in pixels (default 0).
* @param integer $yOffset Vertical offset in pixels (default 0).
* @param bool $calcuateOffsetFromEdge Calculate Offset referring to the edges of the image (default false).
* @param bool $calculateOffsetFromEdge Calculate Offset referring to the edges of the image (default false).
* @return \claviska\SimpleImage
*/
public function overlay($overlay, $anchor = 'center', $opacity = 1, $xOffset = 0, $yOffset = 0, $calcuateOffsetFromEdge = false) {
public function overlay($overlay, $anchor = 'center', $opacity = 1, $xOffset = 0, $yOffset = 0, $calculateOffsetFromEdge = false) {
// Load overlay image
if(!($overlay instanceof SimpleImage)) $overlay = new SimpleImage($overlay);
@@ -723,21 +740,21 @@ class SimpleImage {
$spaceY = $this->getHeight() - $overlay->getHeight();
// Set default center
$x = ($spaceX / 2) + ($calcuateOffsetFromEdge ? 0 : $xOffset);
$y = ($spaceY / 2) + ($calcuateOffsetFromEdge ? 0 : $yOffset);
$x = ($spaceX / 2) + ($calculateOffsetFromEdge ? 0 : $xOffset);
$y = ($spaceY / 2) + ($calculateOffsetFromEdge ? 0 : $yOffset);
// Determine if top|bottom
if (strpos($anchor, 'top') !== false) {
$y = $yOffset;
} elseif (strpos($anchor, 'bottom') !== false) {
$y = $spaceY + ($calcuateOffsetFromEdge ? -$yOffset : $yOffset);
$y = $spaceY + ($calculateOffsetFromEdge ? -$yOffset : $yOffset);
}
// Determine if left|right
if (strpos($anchor, 'left') !== false) {
$x = $xOffset;
} elseif (strpos($anchor, 'right') !== false) {
$x = $spaceX + ($calcuateOffsetFromEdge ? -$xOffset : $xOffset);
$x = $spaceX + ($calculateOffsetFromEdge ? -$xOffset : $xOffset);
}
// Perform the overlay
@@ -859,7 +876,7 @@ class SimpleImage {
* - x* (integer) - Horizontal offset in pixels.
* - y* (integer) - Vertical offset in pixels.
* - color* (string|array) - The text shadow color.
* - $calcuateOffsetFromEdge (bool) - Calculate Offset referring to the edges of the image (default false).
* - $calculateOffsetFromEdge (bool) - Calculate offsets from the edge of the image (default false).
* - $baselineAlign (bool) - Align the text font with the baseline. (default true).
* @param array $boundary
* If passed, this variable will contain an array with coordinates that surround the text: [x1, y1, x2, y2, width, height].
@@ -885,7 +902,7 @@ class SimpleImage {
'xOffset' => 0,
'yOffset' => 0,
'shadow' => null,
'calcuateOffsetFromEdge' => false,
'calculateOffsetFromEdge' => false,
'baselineAlign' => true
], $options);
@@ -896,7 +913,7 @@ class SimpleImage {
$anchor = $options['anchor'];
$xOffset = $options['xOffset'];
$yOffset = $options['yOffset'];
$calcuateOffsetFromEdge = $options['calcuateOffsetFromEdge'];
$calculateOffsetFromEdge = $options['calculateOffsetFromEdge'];
$baselineAlign = $options['baselineAlign'];
$angle = 0;
@@ -921,31 +938,31 @@ class SimpleImage {
// Calculate Offset referring to the edges of the image.
// Just invert the value for bottom|right;
if ($calcuateOffsetFromEdge == true):
if ($calculateOffsetFromEdge == true) {
if (strpos($anchor, 'bottom') !== false) $yOffset *= -1;
if (strpos($anchor, 'right') !== false) $xOffset *= -1;
endif;
}
// Align the text font with the baseline.
// I use $yOffset to inject the vertical alignment correction value.
if ($baselineAlign == true):
if ($baselineAlign == true) {
// Create a temporary box to obtain the maximum height that this font can use.
$boxFull = imagettfbbox($size, $angle, $fontFile, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890');
// Based on the maximum height, the text is aligned.
if (strpos($anchor, 'bottom') !== false):
if (strpos($anchor, 'bottom') !== false) {
$yOffset -= $boxFull[1];
elseif (strpos($anchor, 'top') !== false):
} elseif (strpos($anchor, 'top') !== false) {
$yOffset += abs($boxFull[5]) - $boxHeight;
else: // center
} else { // center
$boxFullHeight = abs($boxFull[1]) + abs($boxFull[5]);
$yOffset += ($boxFullHeight/2) - ($boxHeight/2) - abs($boxFull[1]);
endif;
}
else:
} else {
// Prevents fonts rendered outside the box boundary from being cut.
// Example: 'Scriptina' font, some letters invade the space of the previous or subsequent letter.
$yOffset -= $boxText[1];
endif;
}
// Prevents fonts rendered outside the box boundary from being cut.
// Example: 'Scriptina' font, some letters invade the space of the previous or subsequent letter.
@@ -953,42 +970,42 @@ class SimpleImage {
// Determine position
switch($anchor) {
case 'top left':
$x = $xOffset;
$y = $yOffset + $boxHeight;
break;
case 'top right':
$x = $this->getWidth() - $boxWidth + $xOffset;
$y = $yOffset + $boxHeight;
break;
case 'top':
$x = ($this->getWidth() / 2) - ($boxWidth / 2) + $xOffset;
$y = $yOffset + $boxHeight;
break;
case 'bottom left':
$x = $xOffset;
$y = $this->getHeight() + $yOffset ;
break;
case 'bottom right':
$x = $this->getWidth() - $boxWidth + $xOffset;
$y = $this->getHeight() + $yOffset;
break;
case 'bottom':
$x = ($this->getWidth() / 2) - ($boxWidth / 2) + $xOffset;
$y = $this->getHeight() + $yOffset;
break;
case 'left':
$x = $xOffset;
$y = ($this->getHeight() / 2) - (($boxHeight / 2) - $boxHeight) + $yOffset;
break;
case 'right';
$x = $this->getWidth() - $boxWidth + $xOffset;
$y = ($this->getHeight() / 2) - (($boxHeight / 2) - $boxHeight) + $yOffset;
break;
default: // center
$x = ($this->getWidth() / 2) - ($boxWidth / 2) + $xOffset;
$y = ($this->getHeight() / 2) - (($boxHeight / 2) - $boxHeight) + $yOffset;
break;
case 'top left':
$x = $xOffset;
$y = $yOffset + $boxHeight;
break;
case 'top right':
$x = $this->getWidth() - $boxWidth + $xOffset;
$y = $yOffset + $boxHeight;
break;
case 'top':
$x = ($this->getWidth() / 2) - ($boxWidth / 2) + $xOffset;
$y = $yOffset + $boxHeight;
break;
case 'bottom left':
$x = $xOffset;
$y = $this->getHeight() + $yOffset ;
break;
case 'bottom right':
$x = $this->getWidth() - $boxWidth + $xOffset;
$y = $this->getHeight() + $yOffset;
break;
case 'bottom':
$x = ($this->getWidth() / 2) - ($boxWidth / 2) + $xOffset;
$y = $this->getHeight() + $yOffset;
break;
case 'left':
$x = $xOffset;
$y = ($this->getHeight() / 2) - (($boxHeight / 2) - $boxHeight) + $yOffset;
break;
case 'right';
$x = $this->getWidth() - $boxWidth + $xOffset;
$y = ($this->getHeight() / 2) - (($boxHeight / 2) - $boxHeight) + $yOffset;
break;
default: // center
$x = ($this->getWidth() / 2) - ($boxWidth / 2) + $xOffset;
$y = ($this->getHeight() / 2) - (($boxHeight / 2) - $boxHeight) + $yOffset;
break;
}
$x = (int) round($x);
$y = (int) round($y);
@@ -1023,6 +1040,222 @@ class SimpleImage {
return $this;
}
/**
* Adds text with a line break to the image.
*
* @param string $text The desired text.
* @param array $options
* An array of options.
* - fontFile* (string) - The TrueType (or compatible) font file to use.
* - size (integer) - The size of the font in pixels (default 12).
* - color (string|array) - The text color (default black).
* - anchor (string) - The anchor point: 'center', 'top', 'bottom', 'left', 'right', 'top left', 'top right', 'bottom left', 'bottom right' (default 'center').
* - xOffset (integer) - The horizontal offset in pixels (default 0). Has no effect when anchor is 'center'.
* - yOffset (integer) - The vertical offset in pixels (default 0). Has no effect when anchor is 'center'.
* - shadow (array) - Text shadow params.
* - x* (integer) - Horizontal offset in pixels.
* - y* (integer) - Vertical offset in pixels.
* - color* (string|array) - The text shadow color.
* - $calculateOffsetFromEdge (bool) - Calculate offsets from the edge of the image (default false).
* - width (int) - Width of text box (default image width).
* - align (string) - How to align text: 'left', 'right', 'center', 'justify' (default 'left').
* - leading (float) - Increase/decrease spacing between lines of text (default 0).
* - opacity (float) - The opacity level of the text 0-1 (default 1).
* @throws \Exception
* @return \claviska\SimpleImage
*/
public function textBox($text, $options) {
// default width of image
$maxWidth = $this->getWidth();
// Default options
$options = array_merge([
'fontFile' => null,
'size' => 12,
'color' => 'black',
'anchor' => 'center',
'xOffset' => 0,
'yOffset' => 0,
'shadow' => null,
'calculateOffsetFromEdge' => false,
'width' => $maxWidth,
'align' => 'left',
'leading' => 0,
'opacity' => 1
], $options);
// Extract and normalize options
$fontFile = $options['fontFile'];
$fontSize = $fontSizePx = $options['size'];
$fontSize = ($fontSize / 96) * 72; // Convert px to pt (72pt per inch, 96px per inch)
$color = $options['color'];
$anchor = $options['anchor'];
$xOffset = $options['xOffset'];
$yOffset = $options['yOffset'];
$shadow = $options['shadow'];
$calculateOffsetFromEdge = $options['calculateOffsetFromEdge'];
$angle = 0;
$maxWidth = $options['width'];
$leading = $options['leading'];
$leading = self::keepWithin($leading, ($fontSizePx * -1), $leading);
$opacity = $options['opacity'];
$align = $options['align'];
if ($align == 'right') {
$align = 'top right';
} elseif ($align == 'center') {
$align = 'top';
} elseif ($align == 'justify') {
$align = 'justify';
} else {
$align = 'top left';
}
list($lines, $isLastLine, $lastLineHeight) = self::textSeparateLines($text, $fontFile, $fontSize, $maxWidth);
$maxHeight = (count($lines) - 1) * ($fontSizePx * 1.2 + $leading) + $lastLineHeight;
$imageText = new SimpleImage();
$imageText->fromNew($maxWidth, $maxHeight);
// Align left/center/right
if ($align <> 'justify') {
foreach ($lines as $key => $line) {
if( $align == 'top' ) $line = trim($line); // If is justify = 'center'
$imageText->text($line, array(
'fontFile' => $fontFile,
'size' => $fontSizePx,
'color' => $color,
'anchor' => $align,
'xOffset' => 0,
'yOffset' => $key * ($fontSizePx * 1.2 + $leading),
'shadow' => $shadow,
'calculateOffsetFromEdge' => true
));
}
// Justify
} else {
foreach ($lines as $keyLine => $line) {
// Check if there are spaces at the beginning of the sentence
$spaces = 0;
if (preg_match("/^\s+/", $line, $match)) {
// Count spaces
$spaces = strlen($match[0]);
$line = ltrim($line);
}
// Separate words
$words = preg_split("/\s+/", $line);
// Include spaces with the first word
$words[0] = str_repeat(' ', $spaces) . $words[0];
// Calculates the space occupied by all words
$wordsSize = array();
foreach ($words as $key => $word) {
$wordBox = imagettfbbox($fontSize, 0, $fontFile, $word);
$wordWidth = abs($wordBox[4] - $wordBox[0]);
$wordsSize[$key] = $wordWidth;
}
$wordsSizeTotal = array_sum($wordsSize);
// Calculates the required space between words
$countWords = count($words);
$wordSpacing = 0;
if ($countWords > 1) {
$wordSpacing = ($maxWidth - $wordsSizeTotal) / ($countWords - 1);
$wordSpacing = round($wordSpacing, 3);
}
$xOffsetJustify = 0;
foreach ($words as $key => $word) {
if ($isLastLine[$keyLine] == true) {
if ($key < (count($words) - 1)) continue;
$word = $line;
}
$imageText->text($word, array(
'fontFile' => $fontFile,
'size' => $fontSizePx,
'color' => $color,
'anchor' => 'top left',
'xOffset' => $xOffsetJustify,
'yOffset' => $keyLine * ($fontSizePx * 1.2 + $leading),
'shadow' => $shadow,
'calculateOffsetFromEdge' => true,
)
);
// Calculate offset for next word
$xOffsetJustify += $wordsSize[$key] + $wordSpacing;
}
}
}
$this->overlay($imageText, $anchor, $opacity, $xOffset, $yOffset, $calculateOffsetFromEdge);
return $this;
}
/**
* Receives a text and breaks into LINES.
*
* @param integer $text
* @param string $fontFile
* @param int $fontSize
* @param int $maxWidth
* @return array
*/
private function textSeparateLines($text, $fontFile, $fontSize, $maxWidth) {
$words = self::textSeparateWords($text);
$countWords = count($words) - 1;
$lines[0] = '';
$lineKey = 0;
$isLastLine = [];
for ($i = 0; $i < $countWords; $i++) {
$word = $words[$i];
$isLastLine[$lineKey] = false;
if ($word === PHP_EOL) {
$isLastLine[$lineKey] = true;
$lineKey++;
$lines[$lineKey] = '';
continue;
}
$lineBox = imagettfbbox($fontSize, 0, $fontFile, $lines[$lineKey] . $word);
if (abs($lineBox[4] - $lineBox[0]) < $maxWidth) {
$lines[$lineKey] .= $word . ' ';
} else {
$lineKey++;
$lines[$lineKey] = $word . ' ';
}
}
$isLastLine[$lineKey] = true;
// Exclude space of right
$lines = array_map('rtrim', $lines);
// Calculate height of last line
$boxFull = imagettfbbox($fontSize, 0, $fontFile, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890');
$lineBox = imagettfbbox($fontSize, 0, $fontFile, $lines[$lineKey]);
// Height of last line = ascender of $boxFull + descender of $lineBox
$lastLineHeight = abs($lineBox[1]) + abs($boxFull[5]);
return array($lines, $isLastLine, $lastLineHeight);
}
/**
* Receives a text and breaks into WORD / SPACE / NEW LINE.
*
* @param integer $text
* @return array
*/
private function textSeparateWords($text) {
// Normalizes line break
$text = preg_replace('/(\r\n|\n|\r)/', PHP_EOL, $text);
$text = explode(PHP_EOL, $text);
$newText = array();
foreach ($text as $key => $line) {
$newText = array_merge($newText, explode(' ', $line), [PHP_EOL]);
}
return $newText;
}
/**
* Creates a thumbnail image. This function attempts to get the image as close to the provided
* dimensions as possible, then crops the remaining overflow to force the desired size. Useful
@@ -1125,15 +1358,35 @@ class SimpleImage {
*/
public function arc($x, $y, $width, $height, $start, $end, $color, $thickness = 1) {
// Allocate the color
$color = $this->allocateColor($color);
$tempColor = $this->allocateColor($color);
imagesetthickness($this->image, 1);
// Draw an arc
if($thickness === 'filled') {
imagesetthickness($this->image, 1);
imagefilledarc($this->image, $x, $y, $width, $height, $start, $end, $color, IMG_ARC_PIE);
imagefilledarc($this->image, $x, $y, $width, $height, $start, $end, $tempColor, IMG_ARC_PIE);
} else if ($thickness === 1) {
imagearc($this->image, $x, $y, $width, $height, $start, $end, $tempColor);
} else {
imagesetthickness($this->image, $thickness);
imagearc($this->image, $x, $y, $width, $height, $start, $end, $color);
// New temp image
$tempImage = new SimpleImage();
$tempImage->fromNew($this->getWidth(), $this->getHeight(), 'transparent');
// Draw a large ellipse filled with $color (+$thickness pixels)
$tempColor = $tempImage->allocateColor($color);
imagefilledarc($tempImage->image, $x, $y, $width+$thickness, $height+$thickness, $start, $end, $tempColor, IMG_ARC_PIE);
// Draw a smaller ellipse filled with red|blue (-$thickness pixels)
$tempColor = (self::normalizeColor($color)['red'] == 255) ? 'blue' : 'red';
$tempColor = $tempImage->allocateColor($tempColor);
imagefilledarc($tempImage->image, $x, $y, $width-$thickness, $height-$thickness, $start, $end, $tempColor, IMG_ARC_PIE);
// Replace the color of the smaller ellipse with 'transparent'
$tempImage->excludeInsideColor($x, $y, $color);
// Apply the temp image
$this->overlay($tempImage);
}
return $this;
@@ -1147,15 +1400,14 @@ class SimpleImage {
* @return \claviska\SimpleImage
*/
public function border($color, $thickness = 1) {
$x1 = 0;
$x1 = -1;
$y1 = 0;
$x2 = $this->getWidth() - 1;
$y2 = $this->getHeight() - 1;
$x2 = $this->getWidth();
$y2 = $this->getHeight()-1;
// Draw a border rectangle until it reaches the correct width
for($i = 0; $i < $thickness; $i++) {
$this->rectangle($x1++, $y1++, $x2--, $y2--, $color);
}
$color = $this->allocateColor($color);
imagesetthickness($this->image, $thickness*2);
imagerectangle($this->image, $x1, $y1, $x2, $y2, $color);
return $this;
}
@@ -1188,19 +1440,35 @@ class SimpleImage {
*/
public function ellipse($x, $y, $width, $height, $color, $thickness = 1) {
// Allocate the color
$color = $this->allocateColor($color);
$tempColor = $this->allocateColor($color);
imagesetthickness($this->image, 1);
// Draw an ellipse
if($thickness === 'filled') {
imagesetthickness($this->image, 1);
imagefilledellipse($this->image, $x, $y, $width, $height, $color);
imagefilledellipse($this->image, $x, $y, $width, $height, $tempColor);
} else if ($thickness === 1) {
imageellipse($this->image, $x, $y, $width, $height, $tempColor);
} else {
// imagesetthickness doesn't appear to work with imageellipse, so we work around it.
imagesetthickness($this->image, 1);
$i = 0;
while($i++ < $thickness * 2 - 1) {
imageellipse($this->image, $x, $y, --$width, $height--, $color);
}
// New temp image
$tempImage = new SimpleImage();
$tempImage->fromNew($this->getWidth(), $this->getHeight(), 'transparent');
// Draw a large ellipse filled with $color (+$thickness pixels)
$tempColor = $tempImage->allocateColor($color);
imagefilledellipse($tempImage->image, $x, $y, $width+$thickness, $height+$thickness, $tempColor);
// Draw a smaller ellipse filled with red|blue (-$thickness pixels)
$tempColor = (self::normalizeColor($color)['red'] == 255) ? 'blue' : 'red';
$tempColor = $tempImage->allocateColor($tempColor);
imagefilledellipse($tempImage->image, $x, $y, $width-$thickness, $height-$thickness, $tempColor);
// Replace the color of the smaller ellipse with 'transparent'
$tempImage->excludeInsideColor($x, $y, $color);
// Apply the temp image
$this->overlay($tempImage);
}
return $this;
@@ -1352,7 +1620,7 @@ class SimpleImage {
$tempImage->roundedRectangle($x1, $y1, $x2, $y2, $radius, $color,'filled');
// Draw a smaller rectangle filled with red|blue (-$thickness pixels on each side)
$tempColor = ($color == 'red') ? 'blue' : 'red';
$tempColor = (self::normalizeColor($color)['red'] == 255) ? 'blue' : 'red';
$radius = $radius - $thickness;
$radius = self::keepWithin($radius, 0, $radius);
$tempImage->roundedRectangle(
@@ -1377,7 +1645,7 @@ class SimpleImage {
/**
* Exclude inside color.
* Used only for roundedRectangle()
* Used for roundedRectangle(), ellipse() and arc()
*
* @param number $x certer x of rectangle.
* @param number $y certer y of rectangle.

View File

@@ -42,6 +42,8 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
private $vendorDir;
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
@@ -57,6 +59,13 @@ class ClassLoader
private $missingClasses = array();
private $apcuPrefix;
private static $registeredLoaders = array();
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@@ -300,6 +309,17 @@ class ClassLoader
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
@@ -308,6 +328,10 @@ class ClassLoader
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
@@ -367,6 +391,16 @@ class ClassLoader
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup

View File

@@ -1,7 +1,18 @@
<?php
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
@@ -9,13 +20,15 @@ use Composer\Semver\VersionParser;
class InstalledVersions
{
private static $installed = array (
'root' =>
array (
'pretty_version' => '3.5.4',
'version' => '3.5.4.0',
'pretty_version' => '3.5.5',
'version' => '3.5.5.0',
'aliases' =>
array (
),
@@ -26,26 +39,26 @@ private static $installed = array (
array (
'claviska/simpleimage' =>
array (
'pretty_version' => '3.5.1',
'version' => '3.5.1.0',
'pretty_version' => '3.6.3',
'version' => '3.6.3.0',
'aliases' =>
array (
),
'reference' => 'ab2ab8a4672738ab77b39b00922ee4e79aeadb11',
'reference' => '21b6f4bf4ef1927158b3e29bd0c2d99c6681c750',
),
'filp/whoops' =>
array (
'pretty_version' => '2.9.1',
'version' => '2.9.1.0',
'pretty_version' => '2.12.1',
'version' => '2.12.1.0',
'aliases' =>
array (
),
'reference' => '307fb34a5ab697461ec4c9db865b20ff2fd40771',
'reference' => 'c13c0be93cff50f88bbd70827d993026821914dd',
),
'getkirby/cms' =>
array (
'pretty_version' => '3.5.4',
'version' => '3.5.4.0',
'pretty_version' => '3.5.5',
'version' => '3.5.5.0',
'aliases' =>
array (
),
@@ -71,12 +84,12 @@ private static $installed = array (
),
'laminas/laminas-zendframework-bridge' =>
array (
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'pretty_version' => '1.2.0',
'version' => '1.2.0.0',
'aliases' =>
array (
),
'reference' => '6ede70583e101030bcace4dcddd648f760ddf642',
'reference' => '6cccbddfcfc742eb02158d6137ca5687d92cee32',
),
'league/color-extractor' =>
array (
@@ -114,21 +127,21 @@ private static $installed = array (
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.2.0',
'version' => '6.2.0.0',
'pretty_version' => 'v6.4.1',
'version' => '6.4.1.0',
'aliases' =>
array (
),
'reference' => 'e38888a75c070304ca5514197d4847a59a5c853f',
'reference' => '9256f12d8fb0cd0500f93b19e18c356906cbed3d',
),
'psr/log' =>
array (
'pretty_version' => '1.1.3',
'version' => '1.1.3.0',
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'aliases' =>
array (
),
'reference' => '0f73288fd15629204f9d42b7055f72dacbe811fc',
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
),
'symfony/polyfill-mbstring' =>
array (
@@ -157,6 +170,8 @@ private static $installed = array (
),
),
);
private static $canGetVendors;
private static $installedByVendor = array();
@@ -166,7 +181,16 @@ private static $installed = array (
public static function getInstalledPackages()
{
return array_keys(self::$installed['versions']);
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
@@ -179,7 +203,13 @@ return array_keys(self::$installed['versions']);
public static function isInstalled($packageName)
{
return isset(self::$installed['versions'][$packageName]);
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return true;
}
}
return false;
}
@@ -214,42 +244,50 @@ return $provided->matches($constraint);
public static function getVersionRanges($packageName)
{
if (!isset(self::$installed['versions'][$packageName])) {
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getVersion($packageName)
{
if (!isset(self::$installed['versions'][$packageName])) {
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset(self::$installed['versions'][$packageName]['version'])) {
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return self::$installed['versions'][$packageName]['version'];
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
@@ -258,15 +296,19 @@ return self::$installed['versions'][$packageName]['version'];
public static function getPrettyVersion($packageName)
{
if (!isset(self::$installed['versions'][$packageName])) {
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return self::$installed['versions'][$packageName]['pretty_version'];
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
@@ -275,15 +317,19 @@ return self::$installed['versions'][$packageName]['pretty_version'];
public static function getReference($packageName)
{
if (!isset(self::$installed['versions'][$packageName])) {
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset(self::$installed['versions'][$packageName]['reference'])) {
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return self::$installed['versions'][$packageName]['reference'];
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
@@ -292,7 +338,9 @@ return self::$installed['versions'][$packageName]['reference'];
public static function getRootPackage()
{
return self::$installed['root'];
$installed = self::getInstalled();
return $installed[0]['root'];
}
@@ -327,5 +375,33 @@ return self::$installed;
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
}
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@@ -199,6 +199,11 @@ return array(
'Kirby\\Parsley\\Schema' => $baseDir . '/src/Parsley/Schema.php',
'Kirby\\Parsley\\Schema\\Blocks' => $baseDir . '/src/Parsley/Schema/Blocks.php',
'Kirby\\Parsley\\Schema\\Plain' => $baseDir . '/src/Parsley/Schema/Plain.php',
'Kirby\\Sane\\Handler' => $baseDir . '/src/Sane/Handler.php',
'Kirby\\Sane\\Sane' => $baseDir . '/src/Sane/Sane.php',
'Kirby\\Sane\\Svg' => $baseDir . '/src/Sane/Svg.php',
'Kirby\\Sane\\Svgz' => $baseDir . '/src/Sane/Svgz.php',
'Kirby\\Sane\\Xml' => $baseDir . '/src/Sane/Xml.php',
'Kirby\\Session\\AutoSession' => $baseDir . '/src/Session/AutoSession.php',
'Kirby\\Session\\FileSessionStore' => $baseDir . '/src/Session/FileSessionStore.php',
'Kirby\\Session\\Session' => $baseDir . '/src/Session/Session.php',

View File

@@ -23,7 +23,7 @@ class ComposerAutoloaderInitc26333d865e0329b638bdc17afd29896
}
spl_autoload_register(array('ComposerAutoloaderInitc26333d865e0329b638bdc17afd29896', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInitc26333d865e0329b638bdc17afd29896', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());

View File

@@ -294,6 +294,11 @@ class ComposerStaticInitc26333d865e0329b638bdc17afd29896
'Kirby\\Parsley\\Schema' => __DIR__ . '/../..' . '/src/Parsley/Schema.php',
'Kirby\\Parsley\\Schema\\Blocks' => __DIR__ . '/../..' . '/src/Parsley/Schema/Blocks.php',
'Kirby\\Parsley\\Schema\\Plain' => __DIR__ . '/../..' . '/src/Parsley/Schema/Plain.php',
'Kirby\\Sane\\Handler' => __DIR__ . '/../..' . '/src/Sane/Handler.php',
'Kirby\\Sane\\Sane' => __DIR__ . '/../..' . '/src/Sane/Sane.php',
'Kirby\\Sane\\Svg' => __DIR__ . '/../..' . '/src/Sane/Svg.php',
'Kirby\\Sane\\Svgz' => __DIR__ . '/../..' . '/src/Sane/Svgz.php',
'Kirby\\Sane\\Xml' => __DIR__ . '/../..' . '/src/Sane/Xml.php',
'Kirby\\Session\\AutoSession' => __DIR__ . '/../..' . '/src/Session/AutoSession.php',
'Kirby\\Session\\FileSessionStore' => __DIR__ . '/../..' . '/src/Session/FileSessionStore.php',
'Kirby\\Session\\Session' => __DIR__ . '/../..' . '/src/Session/Session.php',

View File

@@ -2,17 +2,17 @@
"packages": [
{
"name": "claviska/simpleimage",
"version": "3.5.1",
"version_normalized": "3.5.1.0",
"version": "3.6.3",
"version_normalized": "3.6.3.0",
"source": {
"type": "git",
"url": "https://github.com/claviska/SimpleImage.git",
"reference": "ab2ab8a4672738ab77b39b00922ee4e79aeadb11"
"reference": "21b6f4bf4ef1927158b3e29bd0c2d99c6681c750"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/ab2ab8a4672738ab77b39b00922ee4e79aeadb11",
"reference": "ab2ab8a4672738ab77b39b00922ee4e79aeadb11",
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/21b6f4bf4ef1927158b3e29bd0c2d99c6681c750",
"reference": "21b6f4bf4ef1927158b3e29bd0c2d99c6681c750",
"shasum": ""
},
"require": {
@@ -20,7 +20,7 @@
"league/color-extractor": "0.3.*",
"php": ">=5.6.0"
},
"time": "2020-10-30T20:47:26+00:00",
"time": "2021-04-20T12:18:18+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -42,7 +42,7 @@
"description": "A PHP class that makes working with images as simple as possible.",
"support": {
"issues": "https://github.com/claviska/SimpleImage/issues",
"source": "https://github.com/claviska/SimpleImage/tree/3.5.1"
"source": "https://github.com/claviska/SimpleImage/tree/3.6.3"
},
"funding": [
{
@@ -54,17 +54,17 @@
},
{
"name": "filp/whoops",
"version": "2.9.1",
"version_normalized": "2.9.1.0",
"version": "2.12.1",
"version_normalized": "2.12.1.0",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "307fb34a5ab697461ec4c9db865b20ff2fd40771"
"reference": "c13c0be93cff50f88bbd70827d993026821914dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/307fb34a5ab697461ec4c9db865b20ff2fd40771",
"reference": "307fb34a5ab697461ec4c9db865b20ff2fd40771",
"url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd",
"shasum": ""
},
"require": {
@@ -80,7 +80,7 @@
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
"whoops/soap": "Formats errors as SOAP responses"
},
"time": "2020-11-01T12:00:00+00:00",
"time": "2021-04-25T12:00:00+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -116,8 +116,14 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.9.1"
"source": "https://github.com/filp/whoops/tree/2.12.1"
},
"funding": [
{
"url": "https://github.com/denis-sokolov",
"type": "github"
}
],
"install-path": "../filp/whoops"
},
{
@@ -238,27 +244,29 @@
},
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.1.1",
"version_normalized": "1.1.1.0",
"version": "1.2.0",
"version_normalized": "1.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642"
"reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6cccbddfcfc742eb02158d6137ca5687d92cee32",
"reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0"
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"squizlabs/php_codesniffer": "^3.5"
"psalm/plugin-phpunit": "^0.15.1",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.6"
},
"time": "2020-09-14T14:23:00+00:00",
"time": "2021-02-25T21:54:58+00:00",
"type": "library",
"extra": {
"laminas": {
@@ -472,17 +480,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.2.0",
"version_normalized": "6.2.0.0",
"version": "v6.4.1",
"version_normalized": "6.4.1.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "e38888a75c070304ca5514197d4847a59a5c853f"
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e38888a75c070304ca5514197d4847a59a5c853f",
"reference": "e38888a75c070304ca5514197d4847a59a5c853f",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"shasum": ""
},
"require": {
@@ -500,14 +508,14 @@
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"time": "2020-11-25T15:24:57+00:00",
"time": "2021-04-29T12:25:04+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -539,7 +547,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.2.0"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.4.1"
},
"funding": [
{
@@ -551,23 +559,23 @@
},
{
"name": "psr/log",
"version": "1.1.3",
"version_normalized": "1.1.3.0",
"version": "1.1.4",
"version_normalized": "1.1.4.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2020-03-23T09:12:05+00:00",
"time": "2021-05-03T11:20:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -587,7 +595,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
@@ -598,7 +606,7 @@
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.3"
"source": "https://github.com/php-fig/log/tree/1.1.4"
},
"install-path": "../psr/log"
},

View File

@@ -1,8 +1,8 @@
<?php return array (
'root' =>
array (
'pretty_version' => '3.5.4',
'version' => '3.5.4.0',
'pretty_version' => '3.5.5',
'version' => '3.5.5.0',
'aliases' =>
array (
),
@@ -13,26 +13,26 @@
array (
'claviska/simpleimage' =>
array (
'pretty_version' => '3.5.1',
'version' => '3.5.1.0',
'pretty_version' => '3.6.3',
'version' => '3.6.3.0',
'aliases' =>
array (
),
'reference' => 'ab2ab8a4672738ab77b39b00922ee4e79aeadb11',
'reference' => '21b6f4bf4ef1927158b3e29bd0c2d99c6681c750',
),
'filp/whoops' =>
array (
'pretty_version' => '2.9.1',
'version' => '2.9.1.0',
'pretty_version' => '2.12.1',
'version' => '2.12.1.0',
'aliases' =>
array (
),
'reference' => '307fb34a5ab697461ec4c9db865b20ff2fd40771',
'reference' => 'c13c0be93cff50f88bbd70827d993026821914dd',
),
'getkirby/cms' =>
array (
'pretty_version' => '3.5.4',
'version' => '3.5.4.0',
'pretty_version' => '3.5.5',
'version' => '3.5.5.0',
'aliases' =>
array (
),
@@ -58,12 +58,12 @@
),
'laminas/laminas-zendframework-bridge' =>
array (
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'pretty_version' => '1.2.0',
'version' => '1.2.0.0',
'aliases' =>
array (
),
'reference' => '6ede70583e101030bcace4dcddd648f760ddf642',
'reference' => '6cccbddfcfc742eb02158d6137ca5687d92cee32',
),
'league/color-extractor' =>
array (
@@ -101,21 +101,21 @@
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.2.0',
'version' => '6.2.0.0',
'pretty_version' => 'v6.4.1',
'version' => '6.4.1.0',
'aliases' =>
array (
),
'reference' => 'e38888a75c070304ca5514197d4847a59a5c853f',
'reference' => '9256f12d8fb0cd0500f93b19e18c356906cbed3d',
),
'psr/log' =>
array (
'pretty_version' => '1.1.3',
'version' => '1.1.3.0',
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'aliases' =>
array (
),
'reference' => '0f73288fd15629204f9d42b7055f72dacbe811fc',
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
),
'symfony/polyfill-mbstring' =>
array (

View File

@@ -11,6 +11,9 @@
"role": "Developer"
}
],
"scripts": {
"test": "phpunit --testdox tests"
},
"require": {
"php": "^5.5.9 || ^7.0 || ^8.0",
"psr/log": "^1.0.1"

View File

@@ -28,7 +28,7 @@ class JsonResponseHandler extends Handler
/**
* Returns errors[[]] instead of error[] to be in compliance with the json:api spec
* @param bool $jsonApi Default is false
* @return $this
* @return static
*/
public function setJsonApi($jsonApi = false)
{
@@ -38,7 +38,7 @@ class JsonResponseHandler extends Handler
/**
* @param bool|null $returnFrames
* @return bool|$this
* @return bool|static
*/
public function addTraceToOutput($returnFrames = null)
{

View File

@@ -97,17 +97,18 @@ class PlainTextHandler extends Handler
* Set var dumper callback function.
*
* @param callable $dumper
* @return void
* @return static
*/
public function setDumper(callable $dumper)
{
$this->dumper = $dumper;
return $this;
}
/**
* Add error trace to output.
* @param bool|null $addTraceToOutput
* @return bool|$this
* @return bool|static
*/
public function addTraceToOutput($addTraceToOutput = null)
{
@@ -122,7 +123,7 @@ class PlainTextHandler extends Handler
/**
* Add previous exceptions to output.
* @param bool|null $addPreviousToOutput
* @return bool|$this
* @return bool|static
*/
public function addPreviousToOutput($addPreviousToOutput = null)
{
@@ -138,7 +139,7 @@ class PlainTextHandler extends Handler
* Add error trace function arguments to output.
* Set to True for all frame args, or integer for the n first frame args.
* @param bool|integer|null $addTraceFunctionArgsToOutput
* @return null|bool|integer
* @return static|bool|integer
*/
public function addTraceFunctionArgsToOutput($addTraceFunctionArgsToOutput = null)
{
@@ -151,6 +152,7 @@ class PlainTextHandler extends Handler
} else {
$this->addTraceFunctionArgsToOutput = $addTraceFunctionArgsToOutput;
}
return $this;
}
/**
@@ -158,10 +160,12 @@ class PlainTextHandler extends Handler
* If the limit is reached, the var_dump output is discarded.
* Prevent memory limit errors.
* @var integer
* @return static
*/
public function setTraceFunctionArgsOutputLimit($traceFunctionArgsOutputLimit)
{
$this->traceFunctionArgsOutputLimit = (integer) $traceFunctionArgsOutputLimit;
return $this;
}
/**
@@ -199,7 +203,7 @@ class PlainTextHandler extends Handler
/**
* Only output to logger.
* @param bool|null $loggerOnly
* @return null|bool
* @return static|bool
*/
public function loggerOnly($loggerOnly = null)
{
@@ -208,6 +212,7 @@ class PlainTextHandler extends Handler
}
$this->loggerOnly = (bool) $loggerOnly;
return $this;
}
/**

View File

@@ -175,6 +175,8 @@ class PrettyPageHandler extends Handler
/**
* @return int|null
*
* @throws \Exception
*/
public function handle()
{
@@ -349,11 +351,12 @@ class PrettyPageHandler extends Handler
* @param string $label
* @param array $data
*
* @return void
* @return static
*/
public function addDataTable($label, array $data)
{
$this->extraTables[$label] = $data;
return $this;
}
/**
@@ -368,7 +371,7 @@ class PrettyPageHandler extends Handler
*
* @throws InvalidArgumentException If $callback is not callable
*
* @return void
* @return static
*/
public function addDataTableCallback($label, /* callable */ $callback)
{
@@ -387,6 +390,8 @@ class PrettyPageHandler extends Handler
return [];
}
};
return $this;
}
/**
@@ -418,7 +423,7 @@ class PrettyPageHandler extends Handler
*
* @param bool|null $value
*
* @return bool|null
* @return bool|static
*/
public function handleUnconditionally($value = null)
{
@@ -427,6 +432,7 @@ class PrettyPageHandler extends Handler
}
$this->handleUnconditionally = (bool) $value;
return $this;
}
/**
@@ -447,11 +453,12 @@ class PrettyPageHandler extends Handler
* @param string $identifier
* @param string|callable $resolver
*
* @return void
* @return static
*/
public function addEditor($identifier, $resolver)
{
$this->editors[$identifier] = $resolver;
return $this;
}
/**
@@ -469,7 +476,7 @@ class PrettyPageHandler extends Handler
*
* @throws InvalidArgumentException If invalid argument identifier provided
*
* @return void
* @return static
*/
public function setEditor($editor)
{
@@ -481,6 +488,7 @@ class PrettyPageHandler extends Handler
}
$this->editor = $editor;
return $this;
}
/**
@@ -591,11 +599,12 @@ class PrettyPageHandler extends Handler
*
* @param string $title
*
* @return void
* @return static
*/
public function setPageTitle($title)
{
$this->pageTitle = (string) $title;
return $this;
}
/**
@@ -615,7 +624,7 @@ class PrettyPageHandler extends Handler
*
* @throws InvalidArgumentException If $path is not a valid directory
*
* @return void
* @return static
*/
public function addResourcePath($path)
{
@@ -626,6 +635,7 @@ class PrettyPageHandler extends Handler
}
array_unshift($this->searchPaths, $path);
return $this;
}
/**
@@ -633,11 +643,12 @@ class PrettyPageHandler extends Handler
*
* @param string|null $name
*
* @return void
* @return static
*/
public function addCustomCss($name)
{
$this->customCss = $name;
return $this;
}
/**
@@ -645,11 +656,12 @@ class PrettyPageHandler extends Handler
*
* @param string|null $name
*
* @return void
* @return static
*/
public function addCustomJs($name)
{
$this->customJs = $name;
return $this;
}
/**
@@ -718,11 +730,12 @@ class PrettyPageHandler extends Handler
*
* @param string $resourcesPath
*
* @return void
* @return static
*/
public function setResourcesPath($resourcesPath)
{
$this->addResourcePath($resourcesPath);
return $this;
}
/**
@@ -767,11 +780,12 @@ class PrettyPageHandler extends Handler
* @param string $key The key within the superglobal
* @see hideSuperglobalKey
*
* @return void
* @return static
*/
public function blacklist($superGlobalName, $key)
{
$this->blacklist[$superGlobalName][] = $key;
return $this;
}
/**
@@ -779,7 +793,7 @@ class PrettyPageHandler extends Handler
*
* @param string $superGlobalName The name of the superglobal array, e.g. '_GET'
* @param string $key The key within the superglobal
* @return void
* @return static
*/
public function hideSuperglobalKey($superGlobalName, $key)
{
@@ -789,9 +803,10 @@ class PrettyPageHandler extends Handler
/**
* Checks all values within the given superGlobal array.
*
* Blacklisted values will be replaced by a equal length string cointaining
* only '*' characters. We intentionally dont rely on $GLOBALS as it
* depends on the 'auto_globals_jit' php.ini setting.
* Blacklisted values will be replaced by a equal length string containing
* only '*' characters for string values.
* Non-string values will be replaced with a fixed asterisk count.
* We intentionally dont rely on $GLOBALS as it depends on the 'auto_globals_jit' php.ini setting.
*
* @param array $superGlobal One of the superglobal arrays
* @param string $superGlobalName The name of the superglobal array, e.g. '_GET'
@@ -805,8 +820,8 @@ class PrettyPageHandler extends Handler
$values = $superGlobal;
foreach ($blacklisted as $key) {
if (isset($superGlobal[$key]) && is_string($superGlobal[$key])) {
$values[$key] = str_repeat('*', strlen($superGlobal[$key]));
if (isset($superGlobal[$key])) {
$values[$key] = str_repeat('*', is_string($superGlobal[$key]) ? strlen($superGlobal[$key]) : 3);
}
}

View File

@@ -23,7 +23,7 @@ class XmlResponseHandler extends Handler
/**
* @param bool|null $returnFrames
* @return bool|$this
* @return bool|static
*/
public function addTraceToOutput($returnFrames = null)
{

View File

@@ -100,7 +100,7 @@ Zepto(function($) {
var clipboard = new Clipboard('.clipboard');
var showTooltip = function(elem, msg) {
elem.setAttribute('class', 'clipboard tooltipped tooltipped-s');
elem.classList.add('tooltipped', 'tooltipped-s');
elem.setAttribute('aria-label', msg);
};
@@ -117,7 +117,7 @@ Zepto(function($) {
var btn = document.querySelector('.clipboard');
btn.addEventListener('mouseleave', function(e) {
e.currentTarget.setAttribute('class', 'clipboard');
e.currentTarget.classList.remove('tooltipped', 'tooltipped-s');
e.currentTarget.removeAttribute('aria-label');
});

View File

@@ -38,6 +38,11 @@ final class Run implements RunInterface
*/
private $sendHttpCode = 500;
/**
* @var integer|false
*/
private $sendExitCode = 1;
/**
* @var HandlerInterface[]
*/
@@ -288,6 +293,31 @@ final class Run implements RunInterface
return $this->sendHttpCode = $code;
}
/**
* Should Whoops exit with a specific code on the CLI if possible?
* Whoops will exit with 1 by default, but you can specify something else.
*
* @param int $code
*
* @return int
*
* @throws InvalidArgumentException
*/
public function sendExitCode($code = null)
{
if (func_num_args() == 0) {
return $this->sendExitCode;
}
if ($code < 0 || 255 <= $code) {
throw new InvalidArgumentException(
"Invalid status code '$code', must be between 0 and 254"
);
}
return $this->sendExitCode = (int) $code;
}
/**
* Should Whoops push output directly to the client?
* If this is false, output will be returned by handleException.
@@ -380,7 +410,9 @@ final class Run implements RunInterface
// HHVM fix for https://github.com/facebook/hhvm/issues/4055
$this->system->flushOutputBuffer();
$this->system->stopExecution(1);
$this->system->stopExecution(
$this->sendExitCode()
);
}
return $output;

View File

@@ -90,6 +90,15 @@ interface RunInterface
*/
public function sendHttpCode($code = null);
/**
* Should Whoops exit with a specific code on the CLI if possible?
* Whoops will exit with 1 by default, but you can specify something else.
*
* @param int $code
* @return int
*/
public function sendExitCode($code = null);
/**
* Should Whoops push output directly to the client?
* If this is false, output will be returned by handleException

View File

@@ -124,6 +124,13 @@ class SystemFacade
*/
public function setHttpResponseCode($httpCode)
{
if (!headers_sent()) {
// Ensure that no 'location' header is present as otherwise this
// will override the HTTP code being set here, and mask the
// expected error page.
header_remove('location');
}
return http_response_code($httpCode);
}

View File

@@ -15,11 +15,13 @@
"forum": "https://discourse.laminas.dev/"
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0"
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"squizlabs/php_codesniffer": "^3.5"
"psalm/plugin-phpunit": "^0.15.1",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.6"
},
"autoload": {
"files": [
@@ -52,6 +54,7 @@
"scripts": {
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"static-analysis": "psalm --shepherd --stats",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
}

View File

@@ -40,7 +40,7 @@
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
@@ -57,5 +57,9 @@
"PHPMailer\\Test\\": "test/"
}
},
"license": "LGPL-2.1-only"
"license": "LGPL-2.1-only",
"scripts": {
"check": "./vendor/bin/phpcs",
"test": "./vendor/bin/phpunit"
}
}

View File

@@ -38,20 +38,20 @@ namespace PHPMailer\PHPMailer;
* Plenty to choose from here:
* @see http://oauth2-client.thephpleague.com/providers/thirdparty/
*/
// @see https://github.com/thephpleague/oauth2-google
//@see https://github.com/thephpleague/oauth2-google
use League\OAuth2\Client\Provider\Google;
// @see https://packagist.org/packages/hayageek/oauth2-yahoo
//@see https://packagist.org/packages/hayageek/oauth2-yahoo
use Hayageek\OAuth2\Client\Provider\Yahoo;
// @see https://github.com/stevenmaguire/oauth2-microsoft
//@see https://github.com/stevenmaguire/oauth2-microsoft
use Stevenmaguire\OAuth2\Client\Provider\Microsoft;
if (!isset($_GET['code']) && !isset($_GET['provider'])) {
?>
<html>
<body>Select Provider:<br/>
<a href='?provider=Google'>Google</a><br/>
<a href='?provider=Yahoo'>Yahoo</a><br/>
<a href='?provider=Microsoft'>Microsoft/Outlook/Hotmail/Live/Office365</a><br/>
<body>Select Provider:<br>
<a href='?provider=Google'>Google</a><br>
<a href='?provider=Yahoo'>Yahoo</a><br>
<a href='?provider=Microsoft'>Microsoft/Outlook/Hotmail/Live/Office365</a><br>
</body>
</html>
<?php
@@ -121,26 +121,26 @@ if (null === $provider) {
}
if (!isset($_GET['code'])) {
// If we don't have an authorization code then get one
//If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl($options);
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
//Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
unset($_SESSION['provider']);
exit('Invalid state');
} else {
unset($_SESSION['provider']);
// Try to get an access token (using the authorization code grant)
//Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken(
'authorization_code',
[
'code' => $_GET['code']
]
);
// Use this to interact with an API on the users behalf
// Use this to get a new access token if the old one expires
//Use this to interact with an API on the users behalf
//Use this to get a new access token if the old one expires
echo 'Refresh Token: ', $token->getRefreshToken();
}

View File

@@ -16,6 +16,8 @@ $PHPMAILER_LANG['file_open'] = 'Chyba souboru: Nelze otevřít soubor
$PHPMAILER_LANG['from_failed'] = 'Následující adresa odesílatele je nesprávná: ';
$PHPMAILER_LANG['instantiate'] = 'Nelze vytvořit instanci emailové funkce.';
$PHPMAILER_LANG['invalid_address'] = 'Neplatná adresa: ';
$PHPMAILER_LANG['invalid_hostentry'] = 'Záznam hostitele je nesprávný: ';
$PHPMAILER_LANG['invalid_host'] = 'Hostitel je nesprávný: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer není podporován.';
$PHPMAILER_LANG['provide_address'] = 'Musíte zadat alespoň jednu emailovou adresu příjemce.';
$PHPMAILER_LANG['recipients_failed'] = 'Chyba SMTP: Následující adresy příjemců nejsou správně: ';

View File

@@ -18,6 +18,8 @@ $PHPMAILER_LANG['file_open'] = 'File Error: Súbor sa otvoriť pre č
$PHPMAILER_LANG['from_failed'] = 'Následujúca adresa From je nesprávna: ';
$PHPMAILER_LANG['instantiate'] = 'Nedá sa vytvoriť inštancia emailovej funkcie.';
$PHPMAILER_LANG['invalid_address'] = 'Neodoslané, emailová adresa je nesprávna: ';
$PHPMAILER_LANG['invalid_hostentry'] = 'Záznam hostiteľa je nesprávny: ';
$PHPMAILER_LANG['invalid_host'] = 'Hostiteľ je nesprávny: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' emailový klient nieje podporovaný.';
$PHPMAILER_LANG['provide_address'] = 'Musíte zadať aspoň jednu emailovú adresu príjemcu.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Adresy príjemcov niesu správne ';

View File

@@ -0,0 +1,28 @@
<?php
/**
* Serbian PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Александар Јевремовић <ajevremovic@gmail.com>
* @author Miloš Milanović <mmilanovic016@gmail.com>
*/
$PHPMAILER_LANG['authenticate'] = 'SMTP greška: autentifikacija nije uspela.';
$PHPMAILER_LANG['connect_host'] = 'SMTP greška: povezivanje sa SMTP serverom nije uspelo.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP greška: podaci nisu prihvaćeni.';
$PHPMAILER_LANG['empty_message'] = 'Sadržaj poruke je prazan.';
$PHPMAILER_LANG['encoding'] = 'Nepoznato kodiranje: ';
$PHPMAILER_LANG['execute'] = 'Nije moguće izvršiti naredbu: ';
$PHPMAILER_LANG['file_access'] = 'Nije moguće pristupiti datoteci: ';
$PHPMAILER_LANG['file_open'] = 'Nije moguće otvoriti datoteku: ';
$PHPMAILER_LANG['from_failed'] = 'SMTP greška: slanje sa sledećih adresa nije uspelo: ';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP greška: slanje na sledeće adrese nije uspelo: ';
$PHPMAILER_LANG['instantiate'] = 'Nije moguće pokrenuti mail funkciju.';
$PHPMAILER_LANG['invalid_address'] = 'Poruka nije poslata. Neispravna adresa: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' majler nije podržan.';
$PHPMAILER_LANG['provide_address'] = 'Definišite bar jednu adresu primaoca.';
$PHPMAILER_LANG['signing'] = 'Greška prilikom prijave: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Povezivanje sa SMTP serverom nije uspelo.';
$PHPMAILER_LANG['smtp_error'] = 'Greška SMTP servera: ';
$PHPMAILER_LANG['variable_set'] = 'Nije moguće zadati niti resetovati promenljivu: ';
$PHPMAILER_LANG['extension_missing'] = 'Nedostaje proširenje: ';

View File

@@ -16,11 +16,11 @@ $PHPMAILER_LANG['file_access'] = 'Немає доступу до фай
$PHPMAILER_LANG['file_open'] = 'Помилка файлової системи: не вдається відкрити файл: ';
$PHPMAILER_LANG['from_failed'] = 'Невірна адреса відправника: ';
$PHPMAILER_LANG['instantiate'] = 'Неможливо запустити функцію mail().';
$PHPMAILER_LANG['provide_address'] = 'Будь-ласка, введіть хоча б одну email-адресу отримувача.';
$PHPMAILER_LANG['provide_address'] = 'Будь ласка, введіть хоча б одну email-адресу отримувача.';
$PHPMAILER_LANG['mailer_not_supported'] = ' - поштовий сервер не підтримується.';
$PHPMAILER_LANG['recipients_failed'] = 'Помилка SMTP: не вдалося відправлення для таких отримувачів: ';
$PHPMAILER_LANG['empty_message'] = 'Пусте повідомлення';
$PHPMAILER_LANG['invalid_address'] = 'Не відправлено через невірний формат email-адреси: ';
$PHPMAILER_LANG['invalid_address'] = 'Не відправлено через неправильний формат email-адреси: ';
$PHPMAILER_LANG['signing'] = 'Помилка підпису: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Помилка з\'єднання з SMTP-сервером';
$PHPMAILER_LANG['smtp_error'] = 'Помилка SMTP-сервера: ';

View File

@@ -123,7 +123,7 @@ class OAuth
*/
public function getOauth64()
{
// Get a new token if it's not available or has expired
//Get a new token if it's not available or has expired
if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
$this->oauthToken = $this->getToken();
}

File diff suppressed because it is too large Load Diff

View File

@@ -46,7 +46,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.2.0';
const VERSION = '6.4.1';
/**
* Default POP3 port number.
@@ -199,13 +199,13 @@ class POP3
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
// If no port value provided, use default
//If no port value provided, use default
if (false === $port) {
$this->port = static::DEFAULT_PORT;
} else {
$this->port = (int) $port;
}
// If no timeout value provided, use default
//If no timeout value provided, use default
if (false === $timeout) {
$this->tval = static::DEFAULT_TIMEOUT;
} else {
@@ -214,9 +214,9 @@ class POP3
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
// Reset the error log
//Reset the error log
$this->errors = [];
// connect
//Connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
@@ -226,7 +226,7 @@ class POP3
return true;
}
}
// We need to disconnect regardless of whether the login succeeded
//We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
@@ -243,7 +243,7 @@ class POP3
*/
public function connect($host, $port = false, $tval = 30)
{
// Are we already connected?
//Are we already connected?
if ($this->connected) {
return true;
}
@@ -256,22 +256,22 @@ class POP3
$port = static::DEFAULT_PORT;
}
// connect to the POP3 server
//Connect to the POP3 server
$errno = 0;
$errstr = '';
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #
$errno, // Error Number
$errstr, // Error Message
$host, //POP3 Host
$port, //Port #
$errno, //Error Number
$errstr, //Error Message
$tval
); // Timeout (seconds)
// Restore the error handler
); //Timeout (seconds)
//Restore the error handler
restore_error_handler();
// Did we connect?
//Did we connect?
if (false === $this->pop_conn) {
// It would appear not...
//It would appear not...
$this->setError(
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
);
@@ -279,14 +279,14 @@ class POP3
return false;
}
// Increase the stream time-out
//Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
// Get the POP3 server response
//Get the POP3 server response
$pop3_response = $this->getResponse();
// Check for the +OK
//Check for the +OK
if ($this->checkResponse($pop3_response)) {
// The connection is established and the POP3 server is talking
//The connection is established and the POP3 server is talking
$this->connected = true;
return true;
@@ -316,11 +316,11 @@ class POP3
$password = $this->password;
}
// Send the Username
//Send the Username
$this->sendString("USER $username" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
// Send the Password
//Send the Password
$this->sendString("PASS $password" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {

View File

@@ -35,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.2.0';
const VERSION = '6.4.1';
/**
* SMTP line break constant.
@@ -312,11 +312,11 @@ class SMTP
*/
public function connect($host, $port = null, $timeout = 30, $options = [])
{
// Clear errors to avoid confusion
//Clear errors to avoid confusion
$this->setError('');
// Make sure we are __not__ connected
//Make sure we are __not__ connected
if ($this->connected()) {
// Already connected, generate error
//Already connected, generate error
$this->setError('Already connected to a server');
return false;
@@ -324,7 +324,7 @@ class SMTP
if (empty($port)) {
$port = self::DEFAULT_PORT;
}
// Connect to the SMTP server
//Connect to the SMTP server
$this->edebug(
"Connection: opening to $host:$port, timeout=$timeout, options=" .
(count($options) > 0 ? var_export($options, true) : 'array()'),
@@ -340,11 +340,23 @@ class SMTP
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
// Get any announcement
//Get any announcement
$this->last_reply = $this->get_lines();
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
return true;
$responseCode = (int)substr($this->last_reply, 0, 3);
if ($responseCode === 220) {
return true;
}
//Anything other than a 220 response means something went wrong
//RFC 5321 says the server will wait for us to send a QUIT in response to a 554 error
//https://tools.ietf.org/html/rfc5321#section-3.1
if ($responseCode === 554) {
$this->quit();
}
//This will handle 421 responses which may not wait for a QUIT (e.g. if the server is being shut down)
$this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION);
$this->close();
return false;
}
/**
@@ -397,7 +409,7 @@ class SMTP
restore_error_handler();
}
// Verify we connected properly
//Verify we connected properly
if (!is_resource($connection)) {
$this->setError(
'Failed to connect to server',
@@ -414,11 +426,11 @@ class SMTP
return false;
}
// SMTP server can take longer to respond, give longer timeout for first read
// Windows does not have support for this timeout function
//SMTP server can take longer to respond, give longer timeout for first read
//Windows does not have support for this timeout function
if (strpos(PHP_OS, 'WIN') !== 0) {
$max = (int)ini_get('max_execution_time');
// Don't bother if unlimited, or if set_time_limit is disabled
//Don't bother if unlimited, or if set_time_limit is disabled
if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit($timeout);
}
@@ -449,7 +461,7 @@ class SMTP
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
// Begin encrypted connection
//Begin encrypted connection
set_error_handler([$this, 'errorHandler']);
$crypto_ok = stream_socket_enable_crypto(
$this->smtp_conn,
@@ -487,11 +499,11 @@ class SMTP
}
if (array_key_exists('EHLO', $this->server_caps)) {
// SMTP extensions are available; try to find a proper authentication method
//SMTP extensions are available; try to find a proper authentication method
if (!array_key_exists('AUTH', $this->server_caps)) {
$this->setError('Authentication is not allowed at this stage');
// 'at this stage' means that auth may be allowed after the stage changes
// e.g. after STARTTLS
//'at this stage' means that auth may be allowed after the stage changes
//e.g. after STARTTLS
return false;
}
@@ -535,12 +547,14 @@ class SMTP
}
switch ($authtype) {
case 'PLAIN':
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
return false;
}
// Send encoded username and password
//Send encoded username and password
if (
//Format from https://tools.ietf.org/html/rfc4616#section-2
//We skip the first field (it's forgery), so the string starts with a null byte
!$this->sendCommand(
'User & Password',
base64_encode("\0" . $username . "\0" . $password),
@@ -551,7 +565,7 @@ class SMTP
}
break;
case 'LOGIN':
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
return false;
}
@@ -563,17 +577,17 @@ class SMTP
}
break;
case 'CRAM-MD5':
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
return false;
}
// Get the challenge
//Get the challenge
$challenge = base64_decode(substr($this->last_reply, 4));
// Build the response
//Build the response
$response = $username . ' ' . $this->hmac($challenge, $password);
// send encoded credentials
//send encoded credentials
return $this->sendCommand('Username', base64_encode($response), 235);
case 'XOAUTH2':
//The OAuth instance must be set up prior to requesting auth.
@@ -582,7 +596,7 @@ class SMTP
}
$oauth = $OAuth->getOauth64();
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
return false;
}
@@ -612,15 +626,15 @@ class SMTP
return hash_hmac('md5', $data, $key);
}
// The following borrowed from
// http://php.net/manual/en/function.mhash.php#27225
//The following borrowed from
//http://php.net/manual/en/function.mhash.php#27225
// RFC 2104 HMAC implementation for php.
// Creates an md5 HMAC.
// Eliminates the need to install mhash to compute a HMAC
// by Lance Rushing
//RFC 2104 HMAC implementation for php.
//Creates an md5 HMAC.
//Eliminates the need to install mhash to compute a HMAC
//by Lance Rushing
$bytelen = 64; // byte length for md5
$bytelen = 64; //byte length for md5
if (strlen($key) > $bytelen) {
$key = pack('H*', md5($key));
}
@@ -643,7 +657,7 @@ class SMTP
if (is_resource($this->smtp_conn)) {
$sock_status = stream_get_meta_data($this->smtp_conn);
if ($sock_status['eof']) {
// The socket is valid but we are not connected
//The socket is valid but we are not connected
$this->edebug(
'SMTP NOTICE: EOF caught while checking if connected',
self::DEBUG_CLIENT
@@ -653,7 +667,7 @@ class SMTP
return false;
}
return true; // everything looks good
return true; //everything looks good
}
return false;
@@ -671,7 +685,7 @@ class SMTP
$this->server_caps = null;
$this->helo_rply = null;
if (is_resource($this->smtp_conn)) {
// close the connection and cleanup
//Close the connection and cleanup
fclose($this->smtp_conn);
$this->smtp_conn = null; //Makes for cleaner serialization
$this->edebug('Connection: closed', self::DEBUG_CONNECTION);
@@ -706,7 +720,7 @@ class SMTP
* NOTE: this does not count towards line-length limit.
*/
// Normalize line breaks before exploding
//Normalize line breaks before exploding
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
@@ -752,7 +766,8 @@ class SMTP
//Send the lines to the server
foreach ($lines_out as $line_out) {
//RFC2821 section 4.5.2
//Dot-stuffing as per RFC5321 section 4.5.2
//https://tools.ietf.org/html/rfc5321#section-4.5.2
if (!empty($line_out) && $line_out[0] === '.') {
$line_out = '.' . $line_out;
}
@@ -786,7 +801,16 @@ class SMTP
public function hello($host = '')
{
//Try extended hello first (RFC 2821)
return $this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host);
if ($this->sendHello('EHLO', $host)) {
return true;
}
//Some servers shut down the SMTP service here (RFC 5321)
if (substr($this->helo_rply, 0, 3) == '421') {
return false;
}
return $this->sendHello('HELO', $host);
}
/**
@@ -976,12 +1000,12 @@ class SMTP
$this->client_send($commandstring . static::LE, $command);
$this->last_reply = $this->get_lines();
// Fetch SMTP code and possible error code explanation
//Fetch SMTP code and possible error code explanation
$matches = [];
if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) {
$code = (int) $matches[1];
$code_ex = (count($matches) > 2 ? $matches[2] : null);
// Cut off error code from each response line
//Cut off error code from each response line
$detail = preg_replace(
"/{$code}[ -]" .
($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m',
@@ -989,7 +1013,7 @@ class SMTP
$this->last_reply
);
} else {
// Fall back to simple parsing if regex fails
//Fall back to simple parsing if regex fails
$code = (int) substr($this->last_reply, 0, 3);
$code_ex = null;
$detail = substr($this->last_reply, 4);
@@ -1184,7 +1208,7 @@ class SMTP
*/
protected function get_lines()
{
// If the connection is bad, give up straight away
//If the connection is bad, give up straight away
if (!is_resource($this->smtp_conn)) {
return '';
}
@@ -1237,13 +1261,13 @@ class SMTP
$str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH);
$this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);
$data .= $str;
// If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
// or 4th character is a space or a line break char, we are done reading, break the loop.
// String array access is a significant micro-optimisation over strlen
//If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
//or 4th character is a space or a line break char, we are done reading, break the loop.
//String array access is a significant micro-optimisation over strlen
if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") {
break;
}
// Timed-out? Log and break
//Timed-out? Log and break
$info = stream_get_meta_data($this->smtp_conn);
if ($info['timed_out']) {
$this->edebug(
@@ -1252,7 +1276,7 @@ class SMTP
);
break;
}
// Now check if reads took too long
//Now check if reads took too long
if ($endtime && time() > $endtime) {
$this->edebug(
'SMTP -> get_lines(): timelimit reached (' .

View File

@@ -14,8 +14,8 @@ abstract class AbstractLogger implements LoggerInterface
/**
* System is unusable.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -30,8 +30,8 @@ abstract class AbstractLogger implements LoggerInterface
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -45,8 +45,8 @@ abstract class AbstractLogger implements LoggerInterface
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -59,8 +59,8 @@ abstract class AbstractLogger implements LoggerInterface
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -75,8 +75,8 @@ abstract class AbstractLogger implements LoggerInterface
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -88,8 +88,8 @@ abstract class AbstractLogger implements LoggerInterface
/**
* Normal but significant events.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -103,8 +103,8 @@ abstract class AbstractLogger implements LoggerInterface
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/
@@ -116,8 +116,8 @@ abstract class AbstractLogger implements LoggerInterface
/**
* Detailed debug information.
*
* @param string $message
* @param array $context
* @param string $message
* @param mixed[] $context
*
* @return void
*/

View File

@@ -10,7 +10,7 @@ trait LoggerAwareTrait
/**
* The logger instance.
*
* @var LoggerInterface
* @var LoggerInterface|null
*/
protected $logger;

View File

@@ -7,7 +7,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
"homepage": "https://www.php-fig.org/"
}
],
"require": {