修复越权

This commit is contained in:
taoser 2023-03-16 22:35:59 +08:00
parent 9c83c4d0cd
commit 88275662c3
52 changed files with 701 additions and 477 deletions

View File

@ -557,9 +557,7 @@ class Addons extends AdminController
$data = Request::only(['id','name','version','uid','price']);
// $url = $this->getSystem()['api_url'].'/v1/createOrder';
// $order = Api::urlPost($url,$data);
$response = HttpHelper::withHost()->post('/v1/createOrder', $data);
if ($response->ok()) {
// $orderData = json_decode(json_encode($response->toJson()->data),TRUE);
View::assign('orderData',$response->toArray()['data']);

View File

@ -66,7 +66,7 @@
//上传头像
upload.render({
elem: '.upload-select'
,url: 'uploads'
,url: "{:url('Addons/uploads')}"
,data: {type:'image'}
,accept: 'images'
,method: 'get'

View File

@ -68,7 +68,7 @@ class Article extends Model
*/
public function add(array $data)
{
$superAdmin = User::where('id',$data['user_id'])->value('auth');
$superAdmin = User::where('id', $data['user_id'])->value('auth');
// 超级管理员无需审核
$data['status'] = $superAdmin ? 1 : Config::get('taoler.config.posts_check');
$msg = $data['status'] ? '发布成功' : '发布成功,请等待审核';

View File

@ -139,7 +139,7 @@ class User extends Model
//重置密码
public function respass($data)
{ //halt($data);
$user = $this->where('id',$data['uid'])->find();
$user = $this->where('id', $data['uid'])->find();
$salt = substr(md5($user['create_time']),-6);
$data['password'] = substr_replace(md5($data['password']),$salt,0,6);
$result = $user->save($data);
@ -153,8 +153,7 @@ class User extends Model
//更新设置
public function setNew($data)
{
$userId = $data['user_id'];
$user = User::where('id',$userId)->find();
$user = User::where('id', session('user_id'))->find();
$result = $user->allowField(['email','active','nickname','sex','city','area_id','sign'])->save($data);
if($result){
return 1;

View File

@ -241,7 +241,8 @@ class Article extends BaseController
// 检验发帖是否开放
if(config('taoler.config.is_post') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止发帖!']);
// 数据
$data = Request::only(['cate_id', 'title', 'title_color', 'user_id', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data = Request::only(['cate_id', 'title', 'title_color', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data['user_id'] = $this->uid;
$tagId = input('tagid');
// 验证码
@ -340,6 +341,7 @@ class Article extends BaseController
if(Request::isAjax()){
$data = Request::only(['id','cate_id','title','title_color','user_id','content','upzip','keywords','description','captcha']);
$data['user_id'] = $this->uid;
$tagId = input('tagid');
// 验证码

View File

@ -119,7 +119,8 @@ class User extends BaseController
public function set()
{
if(Request::isAjax()){
$data = Request::only(['user_id','email','nickname','sex','city','area_id','sign']);
$data = Request::only(['email','nickname','sex','city','area_id','sign']);
$data['user_id'] = $this->uid;
// 过滤
$sign = strtolower($data['sign']);
if(strstr($sign, 'script')) return json(['code'=>-1,'msg'=>'包含有非法字符串script脚本']);

84
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [
{
"name": "bacon/bacon-qr-code",
"version": "2.0.7",
"version": "2.0.8",
"source": {
"type": "git",
"url": "https://github.com/Bacon/BaconQrCode.git",
"reference": "d70c840f68657ce49094b8d91f9ee0cc07fbf66c"
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/d70c840f68657ce49094b8d91f9ee0cc07fbf66c",
"reference": "d70c840f68657ce49094b8d91f9ee0cc07fbf66c",
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
"shasum": "",
"mirrors": [
{
@ -62,9 +62,9 @@
"homepage": "https://github.com/Bacon/BaconQrCode",
"support": {
"issues": "https://github.com/Bacon/BaconQrCode/issues",
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.7"
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
},
"time": "2022-03-14T02:02:36+00:00"
"time": "2022-12-07T17:46:57+00:00"
},
{
"name": "cache/adapter-common",
@ -1488,16 +1488,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.6.4",
"version": "v6.7.1",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b"
"reference": "49cd7ea3d2563f028d7811f06864a53b1f15ff55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a94fdebaea6bd17f51be0c2373ab80d3d681269b",
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/49cd7ea3d2563f028d7811f06864a53b1f15ff55",
"reference": "49cd7ea3d2563f028d7811f06864a53b1f15ff55",
"shasum": "",
"mirrors": [
{
@ -1513,22 +1513,24 @@
"php": ">=5.5.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.6.2",
"yoast/phpunit-polyfills": "^1.0.0"
"squizlabs/php_codesniffer": "^3.7.1",
"yoast/phpunit-polyfills": "^1.0.4"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
"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)"
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
},
"type": "library",
"autoload": {
@ -1560,7 +1562,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.6.4"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.7.1"
},
"funding": [
{
@ -1568,7 +1570,7 @@
"type": "github"
}
],
"time": "2022-08-22T09:22:00+00:00"
"time": "2022-12-08T13:30:06+00:00"
},
{
"name": "psr/cache",
@ -2372,16 +2374,16 @@
},
{
"name": "symfony/var-exporter",
"version": "v5.4.10",
"version": "v5.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
"reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340"
"reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/8fc03ee75eeece3d9be1ef47d26d79bea1afb340",
"reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/2adac0a9b55f9fb40b983b790509581dc3db0fff",
"reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff",
"shasum": "",
"mirrors": [
{
@ -2431,7 +2433,7 @@
"serialize"
],
"support": {
"source": "https://github.com/symfony/var-exporter/tree/v5.4.10"
"source": "https://github.com/symfony/var-exporter/tree/v5.4.17"
},
"funding": [
{
@ -2447,7 +2449,7 @@
"type": "tidelift"
}
],
"time": "2022-05-27T12:56:18+00:00"
"time": "2022-12-22T10:10:04+00:00"
},
{
"name": "taoser/think-addons",
@ -3026,16 +3028,16 @@
},
{
"name": "topthink/think-orm",
"version": "v2.0.54",
"version": "v2.0.56",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-orm.git",
"reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e"
"reference": "75b8512736daaa056d511f42c15bed87c9f3605a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/97b061b47616301ff29fbd4c35ed9184e1162e4e",
"reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/75b8512736daaa056d511f42c15bed87c9f3605a",
"reference": "75b8512736daaa056d511f42c15bed87c9f3605a",
"shasum": "",
"mirrors": [
{
@ -3081,9 +3083,9 @@
],
"support": {
"issues": "https://github.com/top-think/think-orm/issues",
"source": "https://github.com/top-think/think-orm/tree/v2.0.54"
"source": "https://github.com/top-think/think-orm/tree/v2.0.56"
},
"time": "2022-07-05T05:25:51+00:00"
"time": "2022-12-15T02:52:53+00:00"
},
{
"name": "topthink/think-template",
@ -3326,16 +3328,16 @@
},
{
"name": "workerman/workerman",
"version": "v4.1.4",
"version": "v4.1.5",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "83e007acf936e2233ac92d7368b87716f2bae338"
"reference": "16bcfc2c7574feea46cdadaaa8ae73f14d464b21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/83e007acf936e2233ac92d7368b87716f2bae338",
"reference": "83e007acf936e2233ac92d7368b87716f2bae338",
"url": "https://api.github.com/repos/walkor/workerman/zipball/16bcfc2c7574feea46cdadaaa8ae73f14d464b21",
"reference": "16bcfc2c7574feea46cdadaaa8ae73f14d464b21",
"shasum": "",
"mirrors": [
{
@ -3391,7 +3393,7 @@
"type": "patreon"
}
],
"time": "2022-10-09T11:33:14+00:00"
"time": "2022-12-14T11:58:06+00:00"
},
{
"name": "yansongda/pay",
@ -3545,16 +3547,16 @@
},
{
"name": "yzh52521/easyhttp",
"version": "v1.0.4",
"version": "v1.0.5",
"source": {
"type": "git",
"url": "https://github.com/yzh52521/easyhttp.git",
"reference": "e34628f8f90295cf0a19e5cd2bcc4dd19000373b"
"reference": "a74fa5a1d4f701bd20e581b0731e885aac3daf9f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/e34628f8f90295cf0a19e5cd2bcc4dd19000373b",
"reference": "e34628f8f90295cf0a19e5cd2bcc4dd19000373b",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/a74fa5a1d4f701bd20e581b0731e885aac3daf9f",
"reference": "a74fa5a1d4f701bd20e581b0731e885aac3daf9f",
"shasum": "",
"mirrors": [
{
@ -3597,9 +3599,9 @@
],
"support": {
"issues": "https://github.com/yzh52521/easyhttp/issues",
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.4"
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.5"
},
"time": "2022-11-10T01:24:11+00:00"
"time": "2022-12-05T12:18:34+00:00"
}
],
"packages-dev": [

View File

@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改
'appname' => 'TaoLer',
// 版本配置
'version' => '2.1.1',
'version' => '2.1.3',
// 加盐
'salt' => 'taoler',
// 数据库备份目录

View File

@ -106,7 +106,7 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
layer.close(index);
layer.open({
type: 2,
area: ['50%', '65%'],
area: ['55%', '75%'],
fixed: false, //不固定
maxmin: true,
content: 'pay.html'+ "?id=" + data.id+ "&name=" + data.name + "&version=" + data.version + "&uid=" + userinfo.uid + "&price=" + data.price,

View File

@ -34,5 +34,11 @@
"allow-plugins": {
"ocramius/package-versions": true
}
},
"archive": {
"exclude": [
"/test",
"/phpunit.xml.dist"
]
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="BaconQrCode Tests">
<directory>./test</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@ -89,6 +89,9 @@ final class CharacterSetEci extends AbstractEnum
*/
private static $nameToEci;
/**
* @param int[] $values
*/
public function __construct(array $values, string ...$otherEncodingNames)
{
$this->values = $values;

View File

@ -62,7 +62,7 @@ class FormatInformation
/**
* Offset i holds the number of 1 bits in the binary representation of i.
*
* @var array
* @var int[]
*/
private const BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];

View File

@ -42,6 +42,9 @@ final class Mode extends AbstractEnum
*/
private $bits;
/**
* @param int[] $characterCountBitsForVersions
*/
protected function __construct(array $characterCountBitsForVersions, int $bits)
{
$this->characterCountBitsForVersions = $characterCountBitsForVersions;

View File

@ -37,7 +37,7 @@ final class Encoder
/**
* Codec cache.
*
* @var array
* @var array<string,ReedSolomonCodec>
*/
private static $codecs = [];

View File

@ -334,7 +334,7 @@ final class SvgImageBackEnd implements ImageBackEndInterface
$this->xmlWriter->writeAttribute('stop-color', $this->getColorString($startColor));
if ($startColor instanceof Alpha) {
$this->xmlWriter->writeAttribute('stop-opacity', $startColor->getAlpha());
$this->xmlWriter->writeAttribute('stop-opacity', (string) $startColor->getAlpha());
}
$this->xmlWriter->endElement();
@ -344,7 +344,7 @@ final class SvgImageBackEnd implements ImageBackEndInterface
$this->xmlWriter->writeAttribute('stop-color', $this->getColorString($endColor));
if ($endColor instanceof Alpha) {
$this->xmlWriter->writeAttribute('stop-opacity', $endColor->getAlpha());
$this->xmlWriter->writeAttribute('stop-opacity', (string) $endColor->getAlpha());
}
$this->xmlWriter->endElement();

View File

@ -41,7 +41,7 @@ final class EdgeIterator implements IteratorAggregate
}
/**
* @return Edge[]
* @return Traversable<Edge>
*/
public function getIterator() : Traversable
{

View File

@ -136,7 +136,7 @@ final class EllipticArc implements OperationInterface
/**
* @return Curve[]
*/
private function createCurves(float $fromX, $fromY) : array
private function createCurves(float $fromX, float $fromY) : array
{
$xAngle = deg2rad($this->xAxisAngle);
list($centerX, $centerY, $radiusX, $radiusY, $startAngle, $deltaAngle) =

View File

@ -17,10 +17,16 @@ use BaconQrCode\Writer;
use PHPUnit\Framework\TestCase;
use Spatie\Snapshots\MatchesSnapshots;
/**
* @group integration
*/
final class ImagickRenderingTest extends TestCase
{
use MatchesSnapshots;
/**
* @requires extension imagick
*/
public function testGenericQrCode() : void
{
$renderer = new ImageRenderer(
@ -35,6 +41,9 @@ final class ImagickRenderingTest extends TestCase
unlink($tempName);
}
/**
* @requires extension imagick
*/
public function testIssue79() : void
{
$eye = SquareEye::instance();

View File

@ -14,7 +14,7 @@ return array(
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'),
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-orm/src'),
'taoser\\think\\' => array($vendorDir . '/taoser/think-auth/src'),
'taoser\\' => array($vendorDir . '/taoser/think-addons/src', $vendorDir . '/taoser/think-setarr/src'),
'phpspirit\\databackup\\' => array($vendorDir . '/lotofbadcode/phpspirit_databackup/src'),

View File

@ -182,8 +182,8 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
3 => __DIR__ . '/..' . '/topthink/think-template/src',
2 => __DIR__ . '/..' . '/topthink/think-template/src',
3 => __DIR__ . '/..' . '/topthink/think-orm/src',
),
'taoser\\think\\' =>
array (

View File

@ -2,18 +2,24 @@
"packages": [
{
"name": "bacon/bacon-qr-code",
"version": "2.0.7",
"version_normalized": "2.0.7.0",
"version": "2.0.8",
"version_normalized": "2.0.8.0",
"source": {
"type": "git",
"url": "https://github.com/Bacon/BaconQrCode.git",
"reference": "d70c840f68657ce49094b8d91f9ee0cc07fbf66c"
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/d70c840f68657ce49094b8d91f9ee0cc07fbf66c",
"reference": "d70c840f68657ce49094b8d91f9ee0cc07fbf66c",
"shasum": ""
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"dasprid/enum": "^1.0.3",
@ -29,7 +35,7 @@
"suggest": {
"ext-imagick": "to generate QR code images"
},
"time": "2022-03-14T02:02:36+00:00",
"time": "2022-12-07T17:46:57+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -53,7 +59,7 @@
"homepage": "https://github.com/Bacon/BaconQrCode",
"support": {
"issues": "https://github.com/Bacon/BaconQrCode/issues",
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.7"
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
},
"install-path": "../bacon/bacon-qr-code"
},
@ -1437,17 +1443,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.6.4",
"version_normalized": "6.6.4.0",
"version": "v6.7.1",
"version_normalized": "6.7.1.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b"
"reference": "49cd7ea3d2563f028d7811f06864a53b1f15ff55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a94fdebaea6bd17f51be0c2373ab80d3d681269b",
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/49cd7ea3d2563f028d7811f06864a53b1f15ff55",
"reference": "49cd7ea3d2563f028d7811f06864a53b1f15ff55",
"shasum": "",
"mirrors": [
{
@ -1463,24 +1469,26 @@
"php": ">=5.5.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.6.2",
"yoast/phpunit-polyfills": "^1.0.0"
"squizlabs/php_codesniffer": "^3.7.1",
"yoast/phpunit-polyfills": "^1.0.4"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
"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)"
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
},
"time": "2022-08-22T09:22:00+00:00",
"time": "2022-12-08T13:30:06+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1512,7 +1520,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.6.4"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.7.1"
},
"funding": [
{
@ -2336,18 +2344,24 @@
},
{
"name": "symfony/var-exporter",
"version": "v5.4.10",
"version_normalized": "5.4.10.0",
"version": "v5.4.17",
"version_normalized": "5.4.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
"reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340"
"reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/8fc03ee75eeece3d9be1ef47d26d79bea1afb340",
"reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340",
"shasum": ""
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/2adac0a9b55f9fb40b983b790509581dc3db0fff",
"reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2.5",
@ -2356,7 +2370,7 @@
"require-dev": {
"symfony/var-dumper": "^4.4.9|^5.0.9|^6.0"
},
"time": "2022-05-27T12:56:18+00:00",
"time": "2022-12-22T10:10:04+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -2392,7 +2406,7 @@
"serialize"
],
"support": {
"source": "https://github.com/symfony/var-exporter/tree/v5.4.10"
"source": "https://github.com/symfony/var-exporter/tree/v5.4.17"
},
"funding": [
{
@ -2983,17 +2997,17 @@
},
{
"name": "topthink/think-orm",
"version": "v2.0.54",
"version_normalized": "2.0.54.0",
"version": "v2.0.56",
"version_normalized": "2.0.56.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-orm.git",
"reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e"
"reference": "75b8512736daaa056d511f42c15bed87c9f3605a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/97b061b47616301ff29fbd4c35ed9184e1162e4e",
"reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/75b8512736daaa056d511f42c15bed87c9f3605a",
"reference": "75b8512736daaa056d511f42c15bed87c9f3605a",
"shasum": "",
"mirrors": [
{
@ -3013,7 +3027,7 @@
"require-dev": {
"phpunit/phpunit": "^7|^8|^9.5"
},
"time": "2022-07-05T05:25:51+00:00",
"time": "2022-12-15T02:52:53+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -3041,7 +3055,7 @@
],
"support": {
"issues": "https://github.com/top-think/think-orm/issues",
"source": "https://github.com/top-think/think-orm/tree/v2.0.54"
"source": "https://github.com/top-think/think-orm/tree/v2.0.56"
},
"install-path": "../topthink/think-orm"
},
@ -3345,17 +3359,17 @@
},
{
"name": "workerman/workerman",
"version": "v4.1.4",
"version_normalized": "4.1.4.0",
"version": "v4.1.5",
"version_normalized": "4.1.5.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "83e007acf936e2233ac92d7368b87716f2bae338"
"reference": "16bcfc2c7574feea46cdadaaa8ae73f14d464b21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/83e007acf936e2233ac92d7368b87716f2bae338",
"reference": "83e007acf936e2233ac92d7368b87716f2bae338",
"url": "https://api.github.com/repos/walkor/workerman/zipball/16bcfc2c7574feea46cdadaaa8ae73f14d464b21",
"reference": "16bcfc2c7574feea46cdadaaa8ae73f14d464b21",
"shasum": "",
"mirrors": [
{
@ -3370,7 +3384,7 @@
"suggest": {
"ext-event": "For better performance. "
},
"time": "2022-10-09T11:33:14+00:00",
"time": "2022-12-14T11:58:06+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -3561,17 +3575,17 @@
},
{
"name": "yzh52521/easyhttp",
"version": "v1.0.4",
"version_normalized": "1.0.4.0",
"version": "v1.0.5",
"version_normalized": "1.0.5.0",
"source": {
"type": "git",
"url": "https://github.com/yzh52521/easyhttp.git",
"reference": "e34628f8f90295cf0a19e5cd2bcc4dd19000373b"
"reference": "a74fa5a1d4f701bd20e581b0731e885aac3daf9f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/e34628f8f90295cf0a19e5cd2bcc4dd19000373b",
"reference": "e34628f8f90295cf0a19e5cd2bcc4dd19000373b",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/a74fa5a1d4f701bd20e581b0731e885aac3daf9f",
"reference": "a74fa5a1d4f701bd20e581b0731e885aac3daf9f",
"shasum": "",
"mirrors": [
{
@ -3585,7 +3599,7 @@
"php": "^7.2.5|^8.0",
"psr/log": "^1.0|^2.0|^3.0"
},
"time": "2022-11-10T01:24:11+00:00",
"time": "2022-12-05T12:18:34+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -3616,7 +3630,7 @@
],
"support": {
"issues": "https://github.com/yzh52521/easyhttp/issues",
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.4"
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.5"
},
"install-path": "../yzh52521/easyhttp"
}

View File

@ -3,7 +3,7 @@
'name' => 'taoser/taoler',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'e3f1590beb50ab5826fd410fd37264870b5967f4',
'reference' => '09978bd07a1c769bc266ff2cb0c8c639bc3d41e8',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -11,9 +11,9 @@
),
'versions' => array(
'bacon/bacon-qr-code' => array(
'pretty_version' => '2.0.7',
'version' => '2.0.7.0',
'reference' => 'd70c840f68657ce49094b8d91f9ee0cc07fbf66c',
'pretty_version' => '2.0.8',
'version' => '2.0.8.0',
'reference' => '8674e51bb65af933a5ffaf1c308a660387c35c22',
'type' => 'library',
'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
'aliases' => array(),
@ -200,9 +200,9 @@
'dev_requirement' => false,
),
'phpmailer/phpmailer' => array(
'pretty_version' => 'v6.6.4',
'version' => '6.6.4.0',
'reference' => 'a94fdebaea6bd17f51be0c2373ab80d3d681269b',
'pretty_version' => 'v6.7.1',
'version' => '6.7.1.0',
'reference' => '49cd7ea3d2563f028d7811f06864a53b1f15ff55',
'type' => 'library',
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
'aliases' => array(),
@ -347,9 +347,9 @@
'dev_requirement' => false,
),
'symfony/var-exporter' => array(
'pretty_version' => 'v5.4.10',
'version' => '5.4.10.0',
'reference' => '8fc03ee75eeece3d9be1ef47d26d79bea1afb340',
'pretty_version' => 'v5.4.17',
'version' => '5.4.17.0',
'reference' => '2adac0a9b55f9fb40b983b790509581dc3db0fff',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/var-exporter',
'aliases' => array(),
@ -358,7 +358,7 @@
'taoser/taoler' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'e3f1590beb50ab5826fd410fd37264870b5967f4',
'reference' => '09978bd07a1c769bc266ff2cb0c8c639bc3d41e8',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -455,9 +455,9 @@
'dev_requirement' => false,
),
'topthink/think-orm' => array(
'pretty_version' => 'v2.0.54',
'version' => '2.0.54.0',
'reference' => '97b061b47616301ff29fbd4c35ed9184e1162e4e',
'pretty_version' => 'v2.0.56',
'version' => '2.0.56.0',
'reference' => '75b8512736daaa056d511f42c15bed87c9f3605a',
'type' => 'library',
'install_path' => __DIR__ . '/../topthink/think-orm',
'aliases' => array(),
@ -518,9 +518,9 @@
'dev_requirement' => false,
),
'workerman/workerman' => array(
'pretty_version' => 'v4.1.4',
'version' => '4.1.4.0',
'reference' => '83e007acf936e2233ac92d7368b87716f2bae338',
'pretty_version' => 'v4.1.5',
'version' => '4.1.5.0',
'reference' => '16bcfc2c7574feea46cdadaaa8ae73f14d464b21',
'type' => 'library',
'install_path' => __DIR__ . '/../workerman/workerman',
'aliases' => array(),
@ -545,9 +545,9 @@
'dev_requirement' => false,
),
'yzh52521/easyhttp' => array(
'pretty_version' => 'v1.0.4',
'version' => '1.0.4.0',
'reference' => 'e34628f8f90295cf0a19e5cd2bcc4dd19000373b',
'pretty_version' => 'v1.0.5',
'version' => '1.0.5.0',
'reference' => 'a74fa5a1d4f701bd20e581b0731e885aac3daf9f',
'type' => 'library',
'install_path' => __DIR__ . '/../yzh52521/easyhttp',
'aliases' => array(),

View File

@ -16,7 +16,7 @@
- Probably the world's most popular code for sending email from PHP!
- Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! and many more
- Integrated SMTP support send without a local mail server
- Send emails with multiple To, CC, BCC and Reply-to addresses
- Send emails with multiple To, CC, BCC, and Reply-to addresses
- Multipart/alternative emails for mail clients that do not read HTML email
- Add attachments, including inline
- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
@ -25,7 +25,7 @@
- Protects against header injection attacks
- Error messages in over 50 languages!
- DKIM and S/MIME signing support
- Compatible with PHP 5.5 and later, including PHP 8.1
- Compatible with PHP 5.5 and later, including PHP 8.2
- Namespaced to prevent name clashes
- Much more!
@ -38,7 +38,7 @@ The PHP `mail()` function usually sends via a local mail server, typically front
*Please* don't be tempted to do it yourself if you don't use PHPMailer, there are many other excellent libraries that
you should look at before rolling your own. Try [SwiftMailer](https://swiftmailer.symfony.com/)
, [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail) etc.
, [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail), etc.
## License
This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read [LICENSE](https://github.com/PHPMailer/PHPMailer/blob/master/LICENSE) for information on the software availability and distribution.
@ -47,7 +47,7 @@ This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lg
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
```json
"phpmailer/phpmailer": "^6.5"
"phpmailer/phpmailer": "^6.7.1"
```
or run
@ -136,14 +136,14 @@ try {
}
```
You'll find plenty to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder, which covers many common scenarios including sending through gmail, building contact forms, sending to mailing lists, and more.
You'll find plenty to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder, which covers many common scenarios including sending through Gmail, building contact forms, sending to mailing lists, and more.
If you are re-using the instance (e.g. when sending to a mailing list), you may need to clear the recipient list to avoid sending duplicate messages. See [the mailing list example](https://github.com/PHPMailer/PHPMailer/blob/master/examples/mailing_list.phps) for further guidance.
That's it. You should now be ready to use PHPMailer!
## Localization
PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder you'll find many translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder, you'll find many translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
```php
//To load the French version
@ -178,9 +178,9 @@ Please disclose any vulnerabilities found responsibly report security issues
See [SECURITY](https://github.com/PHPMailer/PHPMailer/tree/master/SECURITY.md) and [PHPMailer's security advisories on GitHub](https://github.com/PHPMailer/PHPMailer/security).
## Contributing
Please submit bug reports, suggestions and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
Please submit bug reports, suggestions, and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
We're particularly interested in fixing edge-cases, expanding test coverage and updating translations.
We're particularly interested in fixing edge cases, expanding test coverage, and updating translations.
If you found a mistake in the docs, or want to add something, go ahead and amend the wiki anyone can edit it.
@ -204,7 +204,7 @@ Donations are very welcome, whether in beer 🍺, T-shirts 👕, or cold, hard c
Available as part of the Tidelift Subscription.
The maintainers of PHPMailer and thousands of other packages are working with Tidelift to deliver commercial
support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and
support and maintenance for the open-source packages you use to build your applications. Save time, reduce risk, and
improve code health, while paying the maintainers of the exact packages you
use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-phpmailer-phpmailer?utm_source=packagist-phpmailer-phpmailer&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
@ -222,9 +222,9 @@ See [changelog](changelog.md).
### What's changed since moving from SourceForge?
- Official successor to the SourceForge and Google Code projects.
- Test suite.
- Continuous integration with Github Actions.
- Continuous integration with GitHub Actions.
- Composer support.
- Public development.
- Additional languages and language strings.
- CRAM-MD5 authentication support.
- Preserves full repo history of authors, commits and branches from the original SourceForge project.
- Preserves full repo history of authors, commits, and branches from the original SourceForge project.

View File

@ -1 +1 @@
6.6.4
6.7.1

View File

@ -37,21 +37,23 @@
"ext-hash": "*"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.6.2",
"yoast/phpunit-polyfills": "^1.0.0"
"squizlabs/php_codesniffer": "^3.7.1",
"yoast/phpunit-polyfills": "^1.0.4"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
"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",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"autoload": {

View File

@ -44,6 +44,8 @@ use League\OAuth2\Client\Provider\Google;
use Hayageek\OAuth2\Client\Provider\Yahoo;
//@see https://github.com/stevenmaguire/oauth2-microsoft
use Stevenmaguire\OAuth2\Client\Provider\Microsoft;
//@see https://github.com/greew/oauth2-azure-provider
use Greew\OAuth2\Client\Provider\Azure;
if (!isset($_GET['code']) && !isset($_POST['provider'])) {
?>
@ -57,11 +59,14 @@ if (!isset($_GET['code']) && !isset($_POST['provider'])) {
<label for="providerYahoo">Yahoo</label><br>
<input type="radio" name="provider" value="Microsoft" id="providerMicrosoft">
<label for="providerMicrosoft">Microsoft</label><br>
<input type="radio" name="provider" value="Azure" id="providerAzure">
<label for="providerAzure">Azure</label><br>
<h1>Enter id and secret</h1>
<p>These details are obtained by setting up an app in your provider's developer console.
</p>
<p>ClientId: <input type="text" name="clientId"><p>
<p>ClientSecret: <input type="text" name="clientSecret"></p>
<p>TenantID (only relevant for Azure): <input type="text" name="tenantId"></p>
<input type="submit" value="Continue">
</form>
</body>
@ -77,18 +82,22 @@ session_start();
$providerName = '';
$clientId = '';
$clientSecret = '';
$tenantId = '';
if (array_key_exists('provider', $_POST)) {
$providerName = $_POST['provider'];
$clientId = $_POST['clientId'];
$clientSecret = $_POST['clientSecret'];
$tenantId = $_POST['tenantId'];
$_SESSION['provider'] = $providerName;
$_SESSION['clientId'] = $clientId;
$_SESSION['clientSecret'] = $clientSecret;
$_SESSION['tenantId'] = $tenantId;
} elseif (array_key_exists('provider', $_SESSION)) {
$providerName = $_SESSION['provider'];
$clientId = $_SESSION['clientId'];
$clientSecret = $_SESSION['clientSecret'];
$tenantId = $_SESSION['tenantId'];
}
//If you don't want to use the built-in form, set your client id and secret here
@ -130,6 +139,17 @@ switch ($providerName) {
]
];
break;
case 'Azure':
$params['tenantId'] = $tenantId;
$provider = new Azure($params);
$options = [
'scope' => [
'https://outlook.office.com/SMTP.Send',
'offline_access'
]
];
break;
}
if (null === $provider) {

View File

@ -14,16 +14,22 @@ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP fejl: Data blev ikke accepteret.
$PHPMAILER_LANG['empty_message'] = 'Meddelelsen er uden indhold';
$PHPMAILER_LANG['encoding'] = 'Ukendt encode-format: ';
$PHPMAILER_LANG['execute'] = 'Kunne ikke afvikle: ';
$PHPMAILER_LANG['extension_missing'] = 'Udvidelse mangler: ';
$PHPMAILER_LANG['file_access'] = 'Kunne ikke tilgå filen: ';
$PHPMAILER_LANG['file_open'] = 'Fil fejl: Kunne ikke åbne filen: ';
$PHPMAILER_LANG['from_failed'] = 'Følgende afsenderadresse er forkert: ';
$PHPMAILER_LANG['instantiate'] = 'Email funktionen kunne ikke initialiseres.';
$PHPMAILER_LANG['invalid_address'] = 'Udgyldig adresse: ';
$PHPMAILER_LANG['invalid_header'] = 'Ugyldig header navn eller værdi';
$PHPMAILER_LANG['invalid_hostentry'] = 'Ugyldig hostentry: ';
$PHPMAILER_LANG['invalid_host'] = 'Ugyldig vært: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer understøttes ikke.';
$PHPMAILER_LANG['provide_address'] = 'Indtast mindst en modtagers email adresse.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere er forkerte: ';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere fejlede: ';
$PHPMAILER_LANG['signing'] = 'Signeringsfejl: ';
$PHPMAILER_LANG['smtp_code'] = 'SMTP kode: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Yderligere SMTP info: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fejlede.';
$PHPMAILER_LANG['smtp_detail'] = 'Detalje: ';
$PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: ';
$PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: ';
$PHPMAILER_LANG['extension_missing'] = 'Udvidelse mangler: ';

View File

@ -4,6 +4,7 @@
* Spanish PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Matt Sturdy <matt.sturdy@gmail.com>
* @author Crystopher Glodzienski Cardoso <crystopher.glodzienski@gmail.com>
*/
$PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.';
@ -25,3 +26,6 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falló.';
$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: ';
$PHPMAILER_LANG['smtp_code'] = 'Código del servidor SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Información adicional del servidor SMTP: ';
$PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido';

View File

@ -9,19 +9,18 @@ $PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: Nie można przeprowadzi
$PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: Nie można połączyć się z wybranym hostem.';
$PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: Dane nie zostały przyjęte.';
$PHPMAILER_LANG['empty_message'] = 'Wiadomość jest pusta.';
$PHPMAILER_LANG['encoding'] = 'Nieznany sposób kodowania znaków: ';
$PHPMAILER_LANG['encoding'] = 'Błędny sposób kodowania znaków: ';
$PHPMAILER_LANG['execute'] = 'Nie można uruchomić: ';
$PHPMAILER_LANG['file_access'] = 'Brak dostępu do pliku: ';
$PHPMAILER_LANG['file_open'] = 'Nie można otworzyć pliku: ';
$PHPMAILER_LANG['from_failed'] = 'Następujący adres Nadawcy jest nieprawidłowy: ';
$PHPMAILER_LANG['from_failed'] = 'Następujący adres nadawcy jest nieprawidłowy lub nie istnieje: ';
$PHPMAILER_LANG['instantiate'] = 'Nie można wywołać funkcji mail(). Sprawdź konfigurację serwera.';
$PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości, ' .
'następujący adres Odbiorcy jest nieprawidłowy: ';
$PHPMAILER_LANG['provide_address'] = 'Należy podać prawidłowy adres email Odbiorcy.';
$PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości, ' . 'następujący adres odbiorcy jest nieprawidłowy lub nie istnieje: ';
$PHPMAILER_LANG['provide_address'] = 'Należy podać prawidłowy adres email odbiorcy.';
$PHPMAILER_LANG['mailer_not_supported'] = 'Wybrana metoda wysyłki wiadomości nie jest obsługiwana.';
$PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi: ';
$PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi lub nie istnieją: ';
$PHPMAILER_LANG['signing'] = 'Błąd podpisywania wiadomości: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() zakończone niepowodzeniem.';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Wywołanie funkcji SMTP Connect() zostało zakończone niepowodzeniem.';
$PHPMAILER_LANG['smtp_error'] = 'Błąd SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Nie można ustawić lub zmodyfikować zmiennej: ';
$PHPMAILER_LANG['extension_missing'] = 'Brakujące rozszerzenie: ';

View File

@ -750,7 +750,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.6.4';
const VERSION = '6.7.1';
/**
* Error severity: message only, continue processing.
@ -858,7 +858,7 @@ class PHPMailer
private function mailPassthru($to, $subject, $body, $header, $params)
{
//Check overloading of mail function to avoid double-encoding
if (ini_get('mbstring.func_overload') & 1) {
if ((int)ini_get('mbstring.func_overload') & 1) {
$subject = $this->secureHeader($subject);
} else {
$subject = $this->encodeHeader($this->secureHeader($subject));
@ -1124,6 +1124,22 @@ class PHPMailer
return call_user_func_array([$this, 'addAnAddress'], $params);
}
/**
* Set the boundaries to use for delimiting MIME parts.
* If you override this, ensure you set all 3 boundaries to unique values.
* The default boundaries include a "=_" sequence which cannot occur in quoted-printable bodies,
* as suggested by https://www.rfc-editor.org/rfc/rfc2045#section-6.7
*
* @return void
*/
public function setBoundaries()
{
$this->uniqueid = $this->generateId();
$this->boundary[1] = 'b1=_' . $this->uniqueid;
$this->boundary[2] = 'b2=_' . $this->uniqueid;
$this->boundary[3] = 'b3=_' . $this->uniqueid;
}
/**
* Add an address to one of the recipient arrays or to the ReplyTo array.
* Addresses that have been added already return false, but do not throw exceptions.
@ -1671,11 +1687,11 @@ class PHPMailer
return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
}
} catch (Exception $exc) {
if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true) {
$this->smtp->reset();
}
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true && $this->smtp->connected()) {
$this->smtp->reset();
}
if ($this->exceptions) {
throw $exc;
}
@ -1863,7 +1879,7 @@ class PHPMailer
if (!static::isPermittedPath($path)) {
return false;
}
$readable = file_exists($path);
$readable = is_file($path);
//If not a UNC path (expected to start with \\), check read permission, see #2069
if (strpos($path, '\\\\') !== 0) {
$readable = $readable && is_readable($path);
@ -2101,6 +2117,9 @@ class PHPMailer
$this->smtp->setDebugLevel($this->SMTPDebug);
$this->smtp->setDebugOutput($this->Debugoutput);
$this->smtp->setVerp($this->do_verp);
if ($this->Host === null) {
$this->Host = 'localhost';
}
$hosts = explode(';', $this->Host);
$lastexception = null;
@ -2791,10 +2810,7 @@ class PHPMailer
{
$body = '';
//Create unique IDs and preset boundaries
$this->uniqueid = $this->generateId();
$this->boundary[1] = 'b1_' . $this->uniqueid;
$this->boundary[2] = 'b2_' . $this->uniqueid;
$this->boundary[3] = 'b3_' . $this->uniqueid;
$this->setBoundaries();
if ($this->sign_key_file) {
$body .= $this->getMailMIME() . static::$LE;
@ -2830,7 +2846,7 @@ class PHPMailer
$altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
}
//Use this as a preamble in all multipart message types
$mimepre = 'This is a multi-part message in MIME format.' . static::$LE . static::$LE;
$mimepre = '';
switch ($this->message_type) {
case 'inline':
$body .= $mimepre;
@ -3066,6 +3082,18 @@ class PHPMailer
return $body;
}
/**
* Get the boundaries that this message will use
* @return array
*/
public function getBoundaries()
{
if (empty($this->boundary)) {
$this->setBoundaries();
}
return $this->boundary;
}
/**
* Return the start of a message boundary.
*
@ -4183,6 +4211,7 @@ class PHPMailer
* @param string $name Custom header name
* @param string|null $value Header value
*
* @return bool True if a header was set successfully
* @throws Exception
*/
public function addCustomHeader($name, $value = null)
@ -4632,15 +4661,27 @@ class PHPMailer
}
/**
* Remove trailing breaks from a string.
* Remove trailing whitespace from a string.
*
* @param string $text
*
* @return string The text to remove whitespace from
*/
public static function stripTrailingWSP($text)
{
return rtrim($text, " \r\n\t");
}
/**
* Strip trailing line breaks from a string.
*
* @param string $text
*
* @return string The text to remove breaks from
*/
public static function stripTrailingWSP($text)
public static function stripTrailingBreaks($text)
{
return rtrim($text, " \r\n\t");
return rtrim($text, "\r\n");
}
/**
@ -4806,7 +4847,7 @@ class PHPMailer
$body = static::normalizeBreaks($body, self::CRLF);
//Reduce multiple trailing line breaks to a single one
return static::stripTrailingWSP($body) . self::CRLF;
return static::stripTrailingBreaks($body) . self::CRLF;
}
/**

View File

@ -46,7 +46,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.6.4';
const VERSION = '6.7.1';
/**
* Default POP3 port number.
@ -337,7 +337,12 @@ class POP3
*/
public function disconnect()
{
$this->sendString('QUIT');
// If could not connect at all, no need to disconnect
if ($this->pop_conn === false) {
return;
}
$this->sendString('QUIT' . static::LE);
// RFC 1939 shows POP3 server sending a +OK response to the QUIT command.
// Try to get it. Ignore any failures here.

View File

@ -35,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.6.4';
const VERSION = '6.7.1';
/**
* SMTP line break constant.
@ -682,7 +682,6 @@ class SMTP
*/
public function close()
{
$this->setError('');
$this->server_caps = null;
$this->helo_rply = null;
if (is_resource($this->smtp_conn)) {

2
vendor/services.php vendored
View File

@ -1,5 +1,5 @@
<?php
// This file is automatically generated at:2022-12-03 13:32:51
// This file is automatically generated at:2023-01-04 21:42:43
declare (strict_types = 1);
return array (
0 => 'taoser\\addons\\Service',

View File

@ -149,6 +149,7 @@ class Exporter
}
if (null !== $sleep) {
if (!isset($sleep[$n]) || ($i && $c !== $class)) {
unset($arrayValue[$name]);
continue;
}
$sleep[$n] = false;
@ -164,6 +165,9 @@ class Exporter
}
}
}
if (method_exists($class, '__unserialize')) {
$properties = $arrayValue;
}
prepare_value:
$objectsPool[$value] = [$id = \count($objectsPool)];

View File

@ -340,6 +340,16 @@ class DbManager
{
return $this->listen;
}
/**
* 获取所有连接实列
* @access public
* @return array
*/
public function getInstance(): array
{
return $this->instance;
}
/**
* 注册回调方法

View File

@ -377,6 +377,19 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
return $this->items;
}
/**
* 设置数据集
*
* @param Collection $items
* @return $this
*/
public function setCollection(Collection $items)
{
$this->items = $items;
return $this;
}
public function isEmpty(): bool
{
return $this->items->isEmpty();

View File

@ -559,23 +559,4 @@ trait ModelRelationQuery
$result->refreshOrigin();
}
/**
* 查询软删除数据
* @access public
* @return Query
*/
public function withTrashed()
{
return $this->model ? $this->model->queryWithTrashed() : $this;
}
/**
* 只查询软删除数据
* @access public
* @return Query
*/
public function onlyTrashed()
{
return $this->model ? $this->model->queryOnlyTrashed() : $this;
}
}

View File

@ -383,7 +383,7 @@ trait Attribute
} elseif (isset($this->type[$name])) {
// 类型转换
$value = $this->writeTransform($value, $this->type[$name]);
} elseif (array_key_exists($name, $this->origin) && is_object($value) && method_exists($value, '__toString')) {
} elseif ((array_key_exists($name, $this->origin) || empty($this->origin)) && is_object($value) && method_exists($value, '__toString')) {
// 对象类型
$value = $value->__toString();
}

View File

@ -18,14 +18,18 @@ use think\Model;
/**
* 数据软删除
* @mixin Model
* @method $this withTrashed()
* @method $this onlyTrashed()
*/
trait SoftDelete
{
/**
* 是否包含软删除数据
* @var bool
*/
protected $withTrashed = false;
public function db($scope = []): Query
{
$query = parent::db($scope);
$this->withNoTrashed($query);
return $query;
}
/**
* 判断当前实例是否被软删除
@ -43,74 +47,18 @@ trait SoftDelete
return false;
}
/**
* 查询软删除数据
* @access public
* @return Query
*/
public static function withTrashed(): Query
public function scopeWithTrashed(Query $query)
{
$model = new static();
return $model->withTrashedData(true)->db();
$query->removeOption('soft_delete');
}
/**
* 查询软删除数据
* @access public
* @return Query
*/
public function queryWithTrashed(): Query
{
return $this->withTrashedData(true)->db();
}
/**
* 是否包含软删除数据
* @access protected
* @param bool $withTrashed 是否包含软删除数据
* @return $this
*/
protected function withTrashedData(bool $withTrashed)
{
$this->withTrashed = $withTrashed;
return $this;
}
/**
* 只查询软删除数据
* @access public
* @return Query
*/
public static function onlyTrashed(): Query
{
$model = new static();
$field = $model->getDeleteTimeField(true);
if ($field) {
return $model
->db()
->useSoftDelete($field, $model->getWithTrashedExp());
}
return $model->db();
}
/**
* 只查询软删除数据
* @access public
* @return Query
*/
public function queryOnlyTrashed(): Query
public function scopeOnlyTrashed(Query $query)
{
$field = $this->getDeleteTimeField(true);
if ($field) {
return $this->db()
->useSoftDelete($field, $this->getWithTrashedExp());
$query->useSoftDelete($field, $this->getWithTrashedExp());
}
return $this->db();
}
/**
@ -139,9 +87,9 @@ trait SoftDelete
if ($name && !$force) {
// 软删除
$this->set($name, $this->autoWriteTimestamp($name));
$this->set($name, $this->autoWriteTimestamp());
$result = $this->exists()->withEvent(false)->save();
$this->exists()->withEvent(false)->save();
$this->withEvent(true);
} else {
@ -149,7 +97,7 @@ trait SoftDelete
$where = $this->getWhere();
// 删除当前模型数据
$result = $this->db()
$this->db()
->where($where)
->removeOption('soft_delete')
->delete();
@ -172,8 +120,8 @@ trait SoftDelete
/**
* 删除记录
* @access public
* @param mixed $data 主键列表 支持闭包查询条件
* @param bool $force 是否强制删除
* @param mixed $data 主键列表 支持闭包查询条件
* @param bool $force 是否强制删除
* @return bool
*/
public static function destroy($data, bool $force = false): bool
@ -182,18 +130,20 @@ trait SoftDelete
if (empty($data) && 0 !== $data) {
return false;
}
// 仅当强制删除时包含软删除数据
$model = (new static());
if ($force) {
$model->withTrashedData(true);
}
$query = $model->db(false);
// 仅当强制删除时包含软删除数据
if ($force) {
$query->removeOption('soft_delete');
}
if (is_array($data) && key($data) !== 0) {
$query->where($data);
$data = null;
} elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $query]);
call_user_func_array($data, [&$query]);
$data = null;
} elseif (is_null($data)) {
return false;
@ -202,6 +152,7 @@ trait SoftDelete
$resultSet = $query->select($data);
foreach ($resultSet as $result) {
/** @var Model $result */
$result->force($force)->delete();
}
@ -211,7 +162,7 @@ trait SoftDelete
/**
* 恢复被软删除的记录
* @access public
* @param array $where 更新条件
* @param array $where 更新条件
* @return bool
*/
public function restore($where = []): bool
@ -243,7 +194,7 @@ trait SoftDelete
/**
* 获取软删除字段
* @access protected
* @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
* @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
* @return string|false
*/
protected function getDeleteTimeField(bool $read = false)
@ -269,7 +220,7 @@ trait SoftDelete
/**
* 查询的时候默认排除软删除数据
* @access protected
* @param Query $query
* @param Query $query
* @return void
*/
protected function withNoTrashed(Query $query): void

View File

@ -179,7 +179,7 @@ trait TimeStamp
protected function formatDateTime($format, $time = 'now', bool $timestamp = false)
{
if (empty($time)) {
return;
return $time;
}
if (false === $format) {

View File

@ -241,7 +241,7 @@ class BelongsTo extends OneToOne
if (!empty($this->bindAttr)) {
// 绑定关联属性
$this->bindAttr($result, $relationModel);
$result->hidden([$relation]);
$result->hidden([$relation], true);
}
}
}
@ -283,7 +283,7 @@ class BelongsTo extends OneToOne
if (!empty($this->bindAttr)) {
// 绑定关联属性
$this->bindAttr($result, $relationModel);
$result->hidden([$relation]);
$result->hidden([$relation], true);
}
}

View File

@ -240,7 +240,7 @@ class HasOne extends OneToOne
if (!empty($this->bindAttr)) {
// 绑定关联属性
$this->bindAttr($result, $relationModel);
$result->hidden([$relation]);
$result->hidden([$relation], true);
}
}
}
@ -282,7 +282,7 @@ class HasOne extends OneToOne
if (!empty($this->bindAttr)) {
// 绑定关联属性
$this->bindAttr($result, $relationModel);
$result->hidden([$relation]);
$result->hidden([$relation], true);
}
}

View File

@ -13,6 +13,7 @@ namespace think\model\relation;
use Closure;
use think\db\exception\DbException as Exception;
use think\db\Query;
use think\helper\Str;
use think\Model;
use think\model\Relation;
@ -46,14 +47,16 @@ class MorphTo extends Relation
*/
protected $relation;
protected $queryCaller = [];
/**
* 架构函数
* @access public
* @param Model $parent 上级模型对象
* @param string $morphType 多态字段名
* @param string $morphKey 外键名
* @param array $alias 多态别名定义
* @param string $relation 关联名
* @param Model $parent 上级模型对象
* @param string $morphType 多态字段名
* @param string $morphKey 外键名
* @param array $alias 多态别名定义
* @param ?string $relation 关联名
*/
public function __construct(Model $parent, string $morphType, string $morphKey, array $alias = [], string $relation = null)
{
@ -80,8 +83,8 @@ class MorphTo extends Relation
/**
* 延迟获取关联数据
* @access public
* @param array $subRelation 子关联名
* @param Closure $closure 闭包查询条件
* @param array $subRelation 子关联名
* @param ?Closure $closure 闭包查询条件
* @return Model
*/
public function getRelation(array $subRelation = [], Closure $closure = null)
@ -95,7 +98,7 @@ class MorphTo extends Relation
// 主键数据
$pk = $this->parent->$morphKey;
$relationModel = (new $model)->relation($subRelation)->find($pk);
$relationModel = $this->buildQuery((new $model)->relation($subRelation))->find($pk);
if ($relationModel) {
$relationModel->setParent(clone $this->parent);
@ -107,11 +110,11 @@ class MorphTo extends Relation
/**
* 根据关联条件查询当前模型
* @access public
* @param string $operator 比较操作符
* @param integer $count 个数
* @param string $id 关联表的统计字段
* @param string $joinType JOIN类型
* @param Query $query Query对象
* @param string $operator 比较操作符
* @param integer $count 个数
* @param string $id 关联表的统计字段
* @param string $joinType JOIN类型
* @param Query $query Query对象
* @return Query
*/
public function has(string $operator = '>=', int $count = 1, string $id = '*', string $joinType = '', Query $query = null)
@ -122,22 +125,46 @@ class MorphTo extends Relation
/**
* 根据关联条件查询当前模型
* @access public
* @param mixed $where 查询条件(数组或者闭包)
* @param mixed $fields 字段
* @param string $joinType JOIN类型
* @param Query $query Query对象
* @param mixed $where 查询条件(数组或者闭包)
* @param mixed $fields 字段
* @param string $joinType JOIN类型
* @param ?Query $query Query对象
* @return Query
*/
public function hasWhere($where = [], $fields = null, string $joinType = '', Query $query = null)
{
throw new Exception('relation not support: hasWhere');
$alias = class_basename($this->parent);
$types = $this->parent->distinct()->column($this->morphType);
$query = $query ?: $this->parent->db();
return $query->alias($alias)
->where(function (Query $query) use ($types, $where, $alias) {
foreach ($types as $type) {
if ($type) {
$query->whereExists(function (Query $query) use ($type, $where, $alias) {
$class = $this->parseModel($type);
/** @var Model $model */
$model = new $class();
$table = $model->getTable();
$query
->table($table)
->where($alias . '.' . $this->morphType, $type)
->whereRaw("`{$alias}`.`{$this->morphKey}`=`{$table}`.`{$model->getPk()}`")
->where($where);
}, 'OR');
}
}
});
}
/**
* 解析模型的完整命名空间
* @access protected
* @param string $model 模型名(或者完整类名)
* @return string
* @param string $model 模型名(或者完整类名)
* @return Model
*/
protected function parseModel(string $model): string
{
@ -158,7 +185,7 @@ class MorphTo extends Relation
/**
* 设置多态别名
* @access public
* @param array $alias 别名定义
* @param array $alias 别名定义
* @return $this
*/
public function setAlias(array $alias)
@ -173,7 +200,7 @@ class MorphTo extends Relation
* @access public
* @return $this
*/
public function removeOption()
public function removeOption(string $option = '')
{
return $this;
}
@ -181,11 +208,11 @@ class MorphTo extends Relation
/**
* 预载入关联查询
* @access public
* @param array $resultSet 数据集
* @param string $relation 当前关联名
* @param array $subRelation 子关联名
* @param Closure $closure 闭包
* @param array $cache 关联缓存
* @param array $resultSet 数据集
* @param string $relation 当前关联名
* @param array $subRelation 子关联名
* @param ?Closure $closure 闭包
* @param array $cache 关联缓存
* @return void
* @throws Exception
*/
@ -211,8 +238,8 @@ class MorphTo extends Relation
if (!\is_null($closure)) {
$obj = $closure($obj);
}
$pk = $obj->getPk();
$list = $obj->with($subRelation)
$pk = $obj->getPk();
$list = $obj->with($subRelation)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->select($val);
$data = [];
@ -242,11 +269,11 @@ class MorphTo extends Relation
/**
* 预载入关联查询
* @access public
* @param Model $result 数据对象
* @param string $relation 当前关联名
* @param array $subRelation 子关联名
* @param Closure $closure 闭包
* @param array $cache 关联缓存
* @param Model $result 数据对象
* @param string $relation 当前关联名
* @param array $subRelation 子关联名
* @param ?Closure $closure 闭包
* @param array $cache 关联缓存
* @return void
*/
public function eagerlyResult(Model $result, string $relation, array $subRelation = [], Closure $closure = null, array $cache = []): void
@ -260,36 +287,42 @@ class MorphTo extends Relation
/**
* 关联统计
* @access public
* @param Model $result 数据对象
* @param Closure $closure 闭包
* @param string $aggregate 聚合查询方法
* @param string $field 字段
* @param Model $result 数据对象
* @param ?Closure $closure 闭包
* @param string $aggregate 聚合查询方法
* @param string $field 字段
* @return integer
*/
public function relationCount(Model $result, Closure $closure = null, string $aggregate = 'count', string $field = '*')
{}
{
}
/**
* 多态MorphTo 关联模型预查询
* @access protected
* @param string $model 关联模型对象
* @param string $relation 关联名
* @param Model $result
* @param array $subRelation 子关联
* @param array $cache 关联缓存
* @param string $model 关联模型对象
* @param string $relation 关联名
* @param Model $result
* @param array $subRelation 子关联
* @param array $cache 关联缓存
* @return void
*/
protected function eagerlyMorphToOne(string $model, string $relation, Model $result, array $subRelation = [], array $cache = []): void
{
// 预载入关联查询 支持嵌套预载入
$pk = $this->parent->{$this->morphKey};
$data = (new $model)->with($subRelation)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->find($pk);
$pk = $this->parent->{$this->morphKey};
if ($data) {
$data->setParent(clone $result);
$data->exists(true);
$data = null;
if (\class_exists($model)) {
$data = (new $model)->with($subRelation)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->find($pk);
if ($data) {
$data->setParent(clone $result);
$data->exists(true);
}
}
$result->setRelation($relation, $data ?: null);
@ -298,8 +331,8 @@ class MorphTo extends Relation
/**
* 添加关联数据
* @access public
* @param Model $model 关联模型对象
* @param string $type 多态类型
* @param Model $model 关联模型对象
* @param string $type 多态类型
* @return Model
*/
public function associate(Model $model, string $type = ''): Model
@ -332,4 +365,18 @@ class MorphTo extends Relation
return $this->parent->setRelation($this->relation, null);
}
protected function buildQuery(Query $query)
{
foreach ($this->queryCaller as $caller) {
call_user_func_array([$query, $caller[0]], $caller[1]);
}
return $query;
}
public function __call($method, $args)
{
$this->queryCaller[] = [$method, $args];
return $this;
}
}

View File

@ -91,9 +91,23 @@ abstract class OneToOne extends Relation
$query->via($joinAlias);
if ($this instanceof BelongsTo) {
$joinOn = $name . '.' . $this->foreignKey . '=' . $joinAlias . '.' . $this->localKey;
$foreignKeyExp = $this->foreignKey;
if (strpos($foreignKeyExp, '.') === false) {
$foreignKeyExp = $name . '.' . $this->foreignKey;
}
$joinOn = $foreignKeyExp . '=' . $joinAlias . '.' . $this->localKey;
} else {
$joinOn = $name . '.' . $this->localKey . '=' . $joinAlias . '.' . $this->foreignKey;
$foreignKeyExp = $this->foreignKey;
if (strpos($foreignKeyExp, '.') === false) {
$foreignKeyExp = $joinAlias . '.' . $this->foreignKey;
}
$joinOn = $name . '.' . $this->localKey . '=' . $foreignKeyExp;
}
if ($closure) {

View File

@ -157,6 +157,13 @@ class TcpConnection extends ConnectionInterface
*/
public $maxSendBufferSize = 1048576;
/**
* Context.
*
* @var array
*/
public $context = null;
/**
* Default send buffer size.
*
@ -170,7 +177,7 @@ class TcpConnection extends ConnectionInterface
* @var int
*/
public $maxPackageSize = 1048576;
/**
* Default maximum acceptable packet size.
*
@ -285,6 +292,7 @@ class TcpConnection extends ConnectionInterface
$this->maxPackageSize = self::$defaultMaxPackageSize;
$this->_remoteAddress = $remote_address;
static::$connections[$this->id] = $this;
$this->context = new \stdClass;
}
/**
@ -720,23 +728,23 @@ class TcpConnection extends ConnectionInterface
return false;
}
$async = $this instanceof AsyncTcpConnection;
/**
* We disabled ssl3 because https://blog.qualys.com/ssllabs/2014/10/15/ssl-3-is-dead-killed-by-the-poodle-attack.
* You can enable ssl3 by the codes below.
*/
* We disabled ssl3 because https://blog.qualys.com/ssllabs/2014/10/15/ssl-3-is-dead-killed-by-the-poodle-attack.
* You can enable ssl3 by the codes below.
*/
/*if($async){
$type = STREAM_CRYPTO_METHOD_SSLv2_CLIENT | STREAM_CRYPTO_METHOD_SSLv23_CLIENT | STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
}else{
$type = STREAM_CRYPTO_METHOD_SSLv2_SERVER | STREAM_CRYPTO_METHOD_SSLv23_SERVER | STREAM_CRYPTO_METHOD_SSLv3_SERVER;
}*/
if($async){
$type = \STREAM_CRYPTO_METHOD_SSLv2_CLIENT | \STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
}else{
$type = \STREAM_CRYPTO_METHOD_SSLv2_SERVER | \STREAM_CRYPTO_METHOD_SSLv23_SERVER;
}
// Hidden error.
\set_error_handler(function($errno, $errstr, $file){
if (!Worker::$daemonize) {
@ -822,7 +830,7 @@ class TcpConnection extends ConnectionInterface
}
$this->_status = self::STATUS_CLOSING;
if ($this->_sendBuffer === '') {
$this->destroy();
} else {
@ -882,7 +890,7 @@ class TcpConnection extends ConnectionInterface
}
return false;
}
/**
* Whether send buffer is Empty.
*
@ -890,7 +898,7 @@ class TcpConnection extends ConnectionInterface
*/
public function bufferIsEmpty()
{
return empty($this->_sendBuffer);
return empty($this->_sendBuffer);
}
/**

View File

@ -565,7 +565,7 @@ class Request
'tmp_name' => $tmp_file,
'size' => $size,
'error' => $error,
'type' => null,
'type' => '',
];
break;
} // Is post field.

View File

@ -11,10 +11,12 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Protocols;
use Workerman\Connection\ConnectionInterface;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
/**
@ -29,6 +31,13 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
*/
const BINARY_TYPE_BLOB = "\x81";
/**
* Websocket blob type.
*
* @var string
*/
const BINARY_TYPE_BLOB_DEFLATE = "\xc1";
/**
* Websocket arraybuffer type.
*
@ -36,10 +45,17 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
*/
const BINARY_TYPE_ARRAYBUFFER = "\x82";
/**
* Websocket arraybuffer type.
*
* @var string
*/
const BINARY_TYPE_ARRAYBUFFER_DEFLATE = "\xc2";
/**
* Check the integrity of the package.
*
* @param string $buffer
* @param string $buffer
* @param ConnectionInterface $connection
* @return int
*/
@ -53,23 +69,23 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
}
// Has not yet completed the handshake.
if (empty($connection->websocketHandshake)) {
if (empty($connection->context->websocketHandshake)) {
return static::dealHandshake($buffer, $connection);
}
// Buffer websocket frame data.
if ($connection->websocketCurrentFrameLength) {
if ($connection->context->websocketCurrentFrameLength) {
// We need more frame data.
if ($connection->websocketCurrentFrameLength > $recv_len) {
if ($connection->context->websocketCurrentFrameLength > $recv_len) {
// Return 0, because it is not clear the full packet length, waiting for the frame of fin=1.
return 0;
}
} else {
$firstbyte = \ord($buffer[0]);
$secondbyte = \ord($buffer[1]);
$data_len = $secondbyte & 127;
$is_fin_frame = $firstbyte >> 7;
$masked = $secondbyte >> 7;
$first_byte = \ord($buffer[0]);
$second_byte = \ord($buffer[1]);
$data_len = $second_byte & 127;
$is_fin_frame = $first_byte >> 7;
$masked = $second_byte >> 7;
if (!$masked) {
Worker::safeEcho("frame not masked so close the connection\n");
@ -77,7 +93,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
return 0;
}
$opcode = $firstbyte & 0xf;
$opcode = $first_byte & 0xf;
switch ($opcode) {
case 0x0:
break;
@ -90,12 +106,11 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
// Close package.
case 0x8:
// Try to emit onWebSocketClose callback.
if (isset($connection->onWebSocketClose) || isset($connection->worker->onWebSocketClose)) {
$close_cb = $connection->onWebSocketClose ?? $connection->worker->onWebSocketClose ?? false;
if ($close_cb) {
try {
\call_user_func(isset($connection->onWebSocketClose)?$connection->onWebSocketClose:$connection->worker->onWebSocketClose, $connection);
} catch (\Exception $e) {
Worker::stopAll(250, $e);
} catch (\Error $e) {
$close_cb($connection);
} catch (\Throwable $e) {
Worker::stopAll(250, $e);
}
} // Close connection.
@ -109,7 +124,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
// Pong package.
case 0xa:
break;
// Wrong opcode.
// Wrong opcode.
default :
Worker::safeEcho("error opcode $opcode and close websocket connection. Buffer:" . bin2hex($buffer) . "\n");
$connection->close();
@ -123,7 +138,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
if ($head_len > $recv_len) {
return 0;
}
$pack = \unpack('nn/ntotal_len', $buffer);
$pack = \unpack('nn/ntotal_len', $buffer);
$data_len = $pack['total_len'];
} else {
if ($data_len === 127) {
@ -131,13 +146,13 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
if ($head_len > $recv_len) {
return 0;
}
$arr = \unpack('n/N2c', $buffer);
$data_len = $arr['c1']*4294967296 + $arr['c2'];
$arr = \unpack('n/N2c', $buffer);
$data_len = $arr['c1'] * 4294967296 + $arr['c2'];
}
}
$current_frame_length = $head_len + $data_len;
$total_package_size = \strlen($connection->websocketDataBuffer) + $current_frame_length;
$total_package_size = \strlen($connection->context->websocketDataBuffer) + $current_frame_length;
if ($total_package_size > $connection->maxPackageSize) {
Worker::safeEcho("error package. package_length=$total_package_size\n");
$connection->close();
@ -151,12 +166,11 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
$connection->consumeRecvBuffer($current_frame_length);
$tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
$connection->websocketType = "\x8a";
if (isset($connection->onWebSocketPing) || isset($connection->worker->onWebSocketPing)) {
$ping_cb = $connection->onWebSocketPing ?? $connection->worker->onWebSocketPing ?? false;
if ($ping_cb) {
try {
\call_user_func(isset($connection->onWebSocketPing)?$connection->onWebSocketPing:$connection->worker->onWebSocketPing, $connection, $ping_data);
} catch (\Exception $e) {
Worker::stopAll(250, $e);
} catch (\Error $e) {
$ping_cb($connection, $ping_data);
} catch (\Throwable $e) {
Worker::stopAll(250, $e);
}
} else {
@ -175,12 +189,11 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
$tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
$connection->websocketType = "\x8a";
// Try to emit onWebSocketPong callback.
if (isset($connection->onWebSocketPong) || isset($connection->worker->onWebSocketPong)) {
$pong_cb = $connection->onWebSocketPong ?? $connection->worker->onWebSocketPong ?? false;
if ($pong_cb) {
try {
\call_user_func(isset($connection->onWebSocketPong)?$connection->onWebSocketPong:$connection->worker->onWebSocketPong, $connection, $pong_data);
} catch (\Exception $e) {
Worker::stopAll(250, $e);
} catch (\Error $e) {
$pong_cb($connection, $pong_data);
} catch (\Throwable $e) {
Worker::stopAll(250, $e);
}
}
@ -193,22 +206,22 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
}
return $current_frame_length;
} else {
$connection->websocketCurrentFrameLength = $current_frame_length;
$connection->context->websocketCurrentFrameLength = $current_frame_length;
}
}
// Received just a frame length data.
if ($connection->websocketCurrentFrameLength === $recv_len) {
if ($connection->context->websocketCurrentFrameLength === $recv_len) {
static::decode($buffer, $connection);
$connection->consumeRecvBuffer($connection->websocketCurrentFrameLength);
$connection->websocketCurrentFrameLength = 0;
$connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength);
$connection->context->websocketCurrentFrameLength = 0;
return 0;
} // The length of the received data is greater than the length of a frame.
elseif ($connection->websocketCurrentFrameLength < $recv_len) {
static::decode(\substr($buffer, 0, $connection->websocketCurrentFrameLength), $connection);
$connection->consumeRecvBuffer($connection->websocketCurrentFrameLength);
$current_frame_length = $connection->websocketCurrentFrameLength;
$connection->websocketCurrentFrameLength = 0;
elseif ($connection->context->websocketCurrentFrameLength < $recv_len) {
static::decode(\substr($buffer, 0, $connection->context->websocketCurrentFrameLength), $connection);
$connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength);
$current_frame_length = $connection->context->websocketCurrentFrameLength;
$connection->context->websocketCurrentFrameLength = 0;
// Continue to read next frame.
return static::input(\substr($buffer, $current_frame_length), $connection);
} // The length of the received data is less than the length of a frame.
@ -220,7 +233,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
/**
* Websocket encode.
*
* @param string $buffer
* @param string $buffer
* @param ConnectionInterface $connection
* @return string
*/
@ -229,12 +242,18 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
if (!is_scalar($buffer)) {
throw new \Exception("You can't send(" . \gettype($buffer) . ") to client, you need to convert it to a string. ");
}
$len = \strlen($buffer);
if (empty($connection->websocketType)) {
$connection->websocketType = static::BINARY_TYPE_BLOB;
}
// permessage-deflate
if (\ord($connection->websocketType) & 64) {
$buffer = static::deflate($connection, $buffer);
}
$first_byte = $connection->websocketType;
$len = \strlen($buffer);
if ($len <= 125) {
$encode_buffer = $first_byte . \chr($len) . $buffer;
@ -247,37 +266,32 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
}
// Handshake not completed so temporary buffer websocket data waiting for send.
if (empty($connection->websocketHandshake)) {
if (empty($connection->tmpWebsocketData)) {
$connection->tmpWebsocketData = '';
if (empty($connection->context->websocketHandshake)) {
if (empty($connection->context->tmpWebsocketData)) {
$connection->context->tmpWebsocketData = '';
}
// If buffer has already full then discard the current package.
if (\strlen($connection->tmpWebsocketData) > $connection->maxSendBufferSize) {
if (\strlen($connection->context->tmpWebsocketData) > $connection->maxSendBufferSize) {
if ($connection->onError) {
try {
\call_user_func($connection->onError, $connection, \WORKERMAN_SEND_FAIL, 'send buffer full and drop package');
} catch (\Exception $e) {
Worker::stopAll(250, $e);
} catch (\Error $e) {
($connection->onError)($connection, ConnectionInterface::SEND_FAIL, 'send buffer full and drop package');
} catch (\Throwable $e) {
Worker::stopAll(250, $e);
}
}
return '';
}
$connection->tmpWebsocketData .= $encode_buffer;
$connection->context->tmpWebsocketData .= $encode_buffer;
// Check buffer is full.
if ($connection->maxSendBufferSize <= \strlen($connection->tmpWebsocketData)) {
if ($connection->maxSendBufferSize <= \strlen($connection->context->tmpWebsocketData)) {
if ($connection->onBufferFull) {
try {
\call_user_func($connection->onBufferFull, $connection);
} catch (\Exception $e) {
Worker::stopAll(250, $e);
} catch (\Error $e) {
($connection->onBufferFull)($connection);
} catch (\Throwable $e) {
Worker::stopAll(250, $e);
}
}
}
// Return empty string.
return '';
}
@ -288,64 +302,125 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
/**
* Websocket decode.
*
* @param string $buffer
* @param string $buffer
* @param ConnectionInterface $connection
* @return string
*/
public static function decode($buffer, ConnectionInterface $connection)
{
$len = \ord($buffer[1]) & 127;
$first_byte = \ord($buffer[0]);
$second_byte = \ord($buffer[1]);
$len = $second_byte & 127;
$is_fin_frame = $first_byte >> 7;
$rsv1 = 64 === ($first_byte & 64);
if ($len === 126) {
$masks = \substr($buffer, 4, 4);
$data = \substr($buffer, 8);
$data = \substr($buffer, 8);
} else {
if ($len === 127) {
$masks = \substr($buffer, 10, 4);
$data = \substr($buffer, 14);
$data = \substr($buffer, 14);
} else {
$masks = \substr($buffer, 2, 4);
$data = \substr($buffer, 6);
$data = \substr($buffer, 6);
}
}
$dataLength = \strlen($data);
$masks = \str_repeat($masks, \floor($dataLength / 4)) . \substr($masks, 0, $dataLength % 4);
$decoded = $data ^ $masks;
if ($connection->websocketCurrentFrameLength) {
$connection->websocketDataBuffer .= $decoded;
return $connection->websocketDataBuffer;
if ($connection->context->websocketCurrentFrameLength) {
$connection->context->websocketDataBuffer .= $decoded;
if ($rsv1) {
return static::inflate($connection, $connection->context->websocketDataBuffer, $is_fin_frame);
}
return $connection->context->websocketDataBuffer;
} else {
if ($connection->websocketDataBuffer !== '') {
$decoded = $connection->websocketDataBuffer . $decoded;
$connection->websocketDataBuffer = '';
if ($connection->context->websocketDataBuffer !== '') {
$decoded = $connection->context->websocketDataBuffer . $decoded;
$connection->context->websocketDataBuffer = '';
}
if ($rsv1) {
return static::inflate($connection, $decoded, $is_fin_frame);
}
return $decoded;
}
}
/**
* Inflate.
*
* @param $connection
* @param $buffer
* @param $is_fin_frame
* @return false|string
*/
protected static function inflate($connection, $buffer, $is_fin_frame)
{
if (!isset($connection->context->inflator)) {
$connection->context->inflator = \inflate_init(
\ZLIB_ENCODING_RAW,
[
'level' => -1,
'memory' => 8,
'window' => 9,
'strategy' => \ZLIB_DEFAULT_STRATEGY
]
);
}
if ($is_fin_frame) {
$buffer .= "\x00\x00\xff\xff";
}
return \inflate_add($connection->context->inflator, $buffer);
}
/**
* Deflate.
*
* @param $connection
* @param $buffer
* @return false|string
*/
protected static function deflate($connection, $buffer)
{
if (!isset($connection->context->deflator)) {
$connection->context->deflator = \deflate_init(
\ZLIB_ENCODING_RAW,
[
'level' => -1,
'memory' => 8,
'window' => 9,
'strategy' => \ZLIB_DEFAULT_STRATEGY
]
);
}
return \substr(\deflate_add($connection->context->deflator, $buffer), 0, -4);
}
/**
* Websocket handshake.
*
* @param string $buffer
* @param string $buffer
* @param TcpConnection $connection
* @return int
*/
public static function dealHandshake($buffer, TcpConnection $connection)
public static function dealHandshake($buffer, $connection)
{
// HTTP protocol.
if (0 === \strpos($buffer, 'GET')) {
// Find \r\n\r\n.
$heder_end_pos = \strpos($buffer, "\r\n\r\n");
if (!$heder_end_pos) {
$header_end_pos = \strpos($buffer, "\r\n\r\n");
if (!$header_end_pos) {
return 0;
}
$header_length = $heder_end_pos + 4;
$header_length = $header_end_pos + 4;
// Get Sec-WebSocket-Key.
$Sec_WebSocket_Key = '';
if (\preg_match("/Sec-WebSocket-Key: *(.*?)\r\n/i", $buffer, $match)) {
$Sec_WebSocket_Key = $match[1];
} else {
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/".Worker::VERSION."\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/".Worker::VERSION."</div>",
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/" . Worker::VERSION . "\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/" . Worker::VERSION . "</div>",
true);
return 0;
}
@ -353,54 +428,22 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
$new_key = \base64_encode(\sha1($Sec_WebSocket_Key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
// Handshake response data.
$handshake_message = "HTTP/1.1 101 Switching Protocols\r\n"
."Upgrade: websocket\r\n"
."Sec-WebSocket-Version: 13\r\n"
."Connection: Upgrade\r\n"
."Sec-WebSocket-Accept: " . $new_key . "\r\n";
. "Upgrade: websocket\r\n"
. "Sec-WebSocket-Version: 13\r\n"
. "Connection: Upgrade\r\n"
. "Sec-WebSocket-Accept: " . $new_key . "\r\n";
// Websocket data buffer.
$connection->websocketDataBuffer = '';
$connection->context->websocketDataBuffer = '';
// Current websocket frame length.
$connection->websocketCurrentFrameLength = 0;
$connection->context->websocketCurrentFrameLength = 0;
// Current websocket frame data.
$connection->websocketCurrentFrameBuffer = '';
$connection->context->websocketCurrentFrameBuffer = '';
// Consume handshake data.
$connection->consumeRecvBuffer($header_length);
// blob or arraybuffer
if (empty($connection->websocketType)) {
$connection->websocketType = static::BINARY_TYPE_BLOB;
}
$has_server_header = false;
if (isset($connection->headers)) {
if (\is_array($connection->headers)) {
foreach ($connection->headers as $header) {
if (\stripos($header, 'Server:') === 0) {
$has_server_header = true;
}
$handshake_message .= "$header\r\n";
}
} else {
if (\stripos($connection->headers, 'Server:') !== false) {
$has_server_header = true;
}
$handshake_message .= "$connection->headers\r\n";
}
}
if (!$has_server_header) {
$handshake_message .= "Server: workerman/".Worker::VERSION."\r\n";
}
$handshake_message .= "\r\n";
// Send handshake response.
$connection->send($handshake_message, true);
// Mark handshake complete..
$connection->websocketHandshake = true;
// Try to emit onWebSocketConnect callback.
$on_websocket_connect = isset($connection->onWebSocketConnect) ? $connection->onWebSocketConnect :
(isset($connection->worker->onWebSocketConnect) ? $connection->worker->onWebSocketConnect : false);
$on_websocket_connect = $connection->onWebSocketConnect ?? $connection->worker->onWebSocketConnect ?? false;
if ($on_websocket_connect) {
static::parseHttpHeader($buffer);
try {
@ -416,24 +459,49 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
$_GET = $_SERVER = $_SESSION = $_COOKIE = array();
}
// blob or arraybuffer
if (empty($connection->websocketType)) {
$connection->websocketType = static::BINARY_TYPE_BLOB;
}
$has_server_header = false;
if (isset($connection->headers)) {
if (\is_array($connection->headers)) {
foreach ($connection->headers as $header) {
if (\stripos($header, 'Server:') === 0) {
$has_server_header = true;
}
$handshake_message .= "$header\r\n";
}
} else {
if (\stripos($connection->headers, 'Server:') !== false) {
$has_server_header = true;
}
$handshake_message .= "$connection->headers\r\n";
}
}
if (!$has_server_header) {
$handshake_message .= "Server: workerman/" . Worker::VERSION . "\r\n";
}
$handshake_message .= "\r\n";
// Send handshake response.
$connection->send($handshake_message, true);
// Mark handshake complete..
$connection->context->websocketHandshake = true;
// There are data waiting to be sent.
if (!empty($connection->tmpWebsocketData)) {
$connection->send($connection->tmpWebsocketData, true);
$connection->tmpWebsocketData = '';
if (!empty($connection->context->tmpWebsocketData)) {
$connection->send($connection->context->tmpWebsocketData, true);
$connection->context->tmpWebsocketData = '';
}
if (\strlen($buffer) > $header_length) {
return static::input(\substr($buffer, $header_length), $connection);
}
return 0;
} // Is flash policy-file-request.
elseif (0 === \strpos($buffer, '<polic')) {
$policy_xml = '<?xml version="1.0"?><cross-domain-policy><site-control permitted-cross-domain-policies="all"/><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>' . "\0";
$connection->send($policy_xml, true);
$connection->consumeRecvBuffer(\strlen($buffer));
return 0;
}
// Bad websocket handshake request.
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/".Worker::VERSION."\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/".Worker::VERSION."</div>",
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/" . Worker::VERSION . "\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/" . Worker::VERSION . "</div>",
true);
return 0;
}
@ -492,4 +560,5 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
$_SERVER['QUERY_STRING'] = '';
}
}
}

View File

@ -210,7 +210,9 @@ class Timer
public static function delAll()
{
self::$_tasks = self::$_status = array();
\pcntl_alarm(0);
if (\function_exists('pcntl_alarm')) {
\pcntl_alarm(0);
}
if (self::$_event) {
self::$_event->clearAllTimer();
}

View File

@ -34,7 +34,7 @@ class Worker
*
* @var string
*/
const VERSION = '4.1.4';
const VERSION = '4.1.5';
/**
* Status starting.
@ -1218,7 +1218,7 @@ class Worker
case \SIGINT:
case \SIGTERM:
case \SIGHUP:
case \SIGTSTP;
case \SIGTSTP:
static::$_gracefulStop = false;
static::stopAll();
break;
@ -1304,7 +1304,7 @@ class Worker
$STDOUT = \fopen(static::$stdoutFile, "a");
$STDERR = \fopen(static::$stdoutFile, "a");
// Fix standard output cannot redirect of PHP 8.1.8's bug
if (\posix_isatty(2)) {
if (\function_exists('posix_isatty') && \posix_isatty(2)) {
\ob_start(function ($string) {
\file_put_contents(static::$stdoutFile, $string, FILE_APPEND);
}, 1);
@ -1610,7 +1610,7 @@ class Worker
// Get uid.
$user_info = \posix_getpwnam($this->user);
if (!$user_info) {
static::log("Warning: User {$this->user} not exsits");
static::log("Warning: User {$this->user} not exists");
return;
}
$uid = $user_info['uid'];
@ -1618,7 +1618,7 @@ class Worker
if ($this->group) {
$group_info = \posix_getgrnam($this->group);
if (!$group_info) {
static::log("Warning: Group {$this->group} not exsits");
static::log("Warning: Group {$this->group} not exists");
return;
}
$gid = $group_info['gid'];

View File

@ -291,7 +291,7 @@ class Request
//请求头
$requestHeaders = [];
foreach ( $request->getHeaders() as $k => $vs ) {
foreach ( (array)$request->getHeaders() as $k => $vs ) {
foreach ( $vs as $v ) {
$requestHeaders[] = "$k: $v";
}
@ -300,7 +300,7 @@ class Request
//响应头
$responseHeaders = [];
foreach ( $response->getHeaders() as $k => $vs ) {
foreach ( (array)$response->getHeaders() as $k => $vs ) {
foreach ( $vs as $v ) {
$responseHeaders[] = "$k: $v";
}

View File

@ -12,7 +12,6 @@
<div class="layui-form layui-form-pane layui-tab-item layui-show">
<div class="layui-form-item">
<label for="L_email" class="layui-form-label">邮箱</label>
<input type="hidden" name="user_id" value="{:session('user_id')}">
<div class="layui-input-inline">
<input type="text" id="L_email" name="email" lay-verify="email" autocomplete="off" value="{$user.email}" class="layui-input" placeholder="{$user.email}">
</div>