From 152d23807f9b492b9c75951c5d6e769b35f26d20 Mon Sep 17 00:00:00 2001
From: witersen <1801168257@qq.com>
Date: Sat, 7 May 2022 14:47:36 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81=E7=BB=93?=
=?UTF-8?q?=E6=9E=84=20=E6=94=AF=E6=8C=81=E5=A4=A7=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=E4=B8=8B=E8=BD=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
01.web/src/views/advance/index.vue | 22 +-
01.web/src/views/index/index.vue | 6 +-
01.web/src/views/layout/basicLayout/index.vue | 2 +-
01.web/src/views/login/index.vue | 4 +-
01.web/src/views/personal/index.vue | 8 +-
01.web/src/views/repositoryGroup/index.vue | 20 +-
01.web/src/views/repositoryInfo/index.vue | 138 +-
01.web/src/views/repositoryUser/index.vue | 14 +-
01.web/src/views/systemLog/index.vue | 4 +-
01.web/webpack.dev.config.js | 6 +-
02.php/api.php | 92 +
02.php/app/controller/Common.php | 60 +
02.php/app/controller/Logs.php | 47 +
02.php/app/controller/Mail.php | 56 +
02.php/app/controller/Personal.php | 56 +
02.php/app/controller/Safe.php | 29 +
02.php/app/controller/Statistics.php | 70 +
02.php/app/controller/Svn.php | 140 +
02.php/app/controller/Svngroup.php | 128 +
02.php/app/controller/Svnrep.php | 264 +
02.php/app/controller/Svnuser.php | 105 +
02.php/app/controller/Update.php | 56 +
02.php/app/controller/base/Base.php | 88 +
.../function/array.php} | 4 +-
.../function/color.php} | 0
.../function/curl.php} | 2 +-
.../function/file.php} | 2 +-
02.php/app/function/ipc.php | 54 +
.../function/json.php} | 0
02.php/app/function/message.php | 42 +
.../function/string.php} | 0
.../function/update.php} | 0
.../service/Common.php} | 46 +-
.../app/controller => app/service}/Logs.php | 30 +-
.../app/controller => app/service}/Mail.php | 24 +-
.../controller => app/service}/Personal.php | 21 +-
02.php/app/service/Safe.php | 19 +
.../controller => app/service}/Statistics.php | 48 +-
.../app/controller => app/service}/Svn.php | 162 +-
.../controller => app/service}/Svngroup.php | 73 +-
.../app/controller => app/service}/Svnrep.php | 179 +-
.../controller => app/service}/Svnuser.php | 78 +-
.../app/controller => app/service}/Update.php | 44 +-
02.php/app/service/base/Base.php | 280 +
.../check.service.php => app/util/Check.php} | 18 +-
02.php/app/util/Config.php | 45 +
.../util/SVNAdmin/Core.php} | 6 +-
.../util/SVNAdmin/Group.php} | 8 +-
.../util/SVNAdmin/Rep.php} | 80 +-
.../util/SVNAdmin/User.php} | 4 +-
02.php/config/daemon.php | 60 +
02.php/config/database.php | 43 +
.../svnadmin_reg.php => config/reg.php} | 0
02.php/config/router.php | 43 +
.../svnadmin_sign.php => config/sign.php} | 0
.../svnadmin_svn.php => config/svn.php} | 5 +-
.../svnadmin_update.php => config/update.php} | 6 +-
.../version.php} | 0
02.php/extension/Medoo-1.7.10/src/Medoo.php | 1852 ++++++
.../language/phpmailer.lang-af.php | 26 +
.../language/phpmailer.lang-ar.php | 27 +
.../language/phpmailer.lang-az.php | 27 +
.../language/phpmailer.lang-ba.php | 27 +
.../language/phpmailer.lang-be.php | 27 +
.../language/phpmailer.lang-bg.php | 27 +
.../language/phpmailer.lang-ca.php | 27 +
.../language/phpmailer.lang-ch.php | 27 +
.../language/phpmailer.lang-cs.php | 28 +
.../language/phpmailer.lang-da.php | 29 +
.../language/phpmailer.lang-de.php | 28 +
.../language/phpmailer.lang-el.php | 26 +
.../language/phpmailer.lang-eo.php | 26 +
.../language/phpmailer.lang-es.php | 27 +
.../language/phpmailer.lang-et.php | 28 +
.../language/phpmailer.lang-fa.php | 28 +
.../language/phpmailer.lang-fi.php | 28 +
.../language/phpmailer.lang-fo.php | 27 +
.../language/phpmailer.lang-fr.php | 38 +
.../language/phpmailer.lang-gl.php | 27 +
.../language/phpmailer.lang-he.php | 27 +
.../language/phpmailer.lang-hi.php | 27 +
.../language/phpmailer.lang-hr.php | 27 +
.../language/phpmailer.lang-hu.php | 27 +
.../language/phpmailer.lang-hy.php | 27 +
.../language/phpmailer.lang-id.php | 31 +
.../language/phpmailer.lang-it.php | 28 +
.../language/phpmailer.lang-ja.php | 29 +
.../language/phpmailer.lang-ka.php | 27 +
.../language/phpmailer.lang-ko.php | 27 +
.../language/phpmailer.lang-lt.php | 27 +
.../language/phpmailer.lang-lv.php | 27 +
.../language/phpmailer.lang-mg.php | 27 +
.../language/phpmailer.lang-ms.php | 27 +
.../language/phpmailer.lang-nb.php | 26 +
.../language/phpmailer.lang-nl.php | 34 +
.../language/phpmailer.lang-pl.php | 27 +
.../language/phpmailer.lang-pt.php | 27 +
.../language/phpmailer.lang-pt_br.php | 38 +
.../language/phpmailer.lang-ro.php | 33 +
.../language/phpmailer.lang-ru.php | 28 +
.../language/phpmailer.lang-sk.php | 30 +
.../language/phpmailer.lang-sl.php | 36 +
.../language/phpmailer.lang-sr.php | 28 +
.../language/phpmailer.lang-sr_latn.php | 28 +
.../language/phpmailer.lang-sv.php | 27 +
.../language/phpmailer.lang-tl.php | 28 +
.../language/phpmailer.lang-tr.php | 31 +
.../language/phpmailer.lang-uk.php | 28 +
.../language/phpmailer.lang-vi.php | 27 +
.../language/phpmailer.lang-zh.php | 29 +
.../language/phpmailer.lang-zh_cn.php | 29 +
.../PHPMailer-6.6.0/src/Exception.php | 40 +
.../extension/PHPMailer-6.6.0/src/OAuth.php | 139 +
.../src/OAuthTokenProvider.php | 44 +
.../PHPMailer-6.6.0/src/PHPMailer.php | 5072 +++++++++++++++++
02.php/extension/PHPMailer-6.6.0/src/POP3.php | 462 ++
02.php/extension/PHPMailer-6.6.0/src/SMTP.php | 1456 +++++
.../Transfer/Transfer.php} | 2 +-
.../Verifycode/Verifycode.php} | 4 +-
02.php/server/svnadmind.php | 293 +
02.php/templete/svnserve/authz | 3 +
02.php/templete/svnserve/passwd | 1 +
02.php/templete/svnserve/servers | 3 +
02.php/templete/svnserve/svnserve | 2 +
02.php/templete/svnserve/svnserve.conf | 6 +
02.php/webman/.gitignore | 7 -
02.php/webman/LICENSE | 21 -
02.php/webman/README.md | 16 -
02.php/webman/app/controller/Core.php | 466 --
02.php/webman/app/controller/Index.php | 40 -
02.php/webman/app/controller/Safe.php | 16 -
.../webman/app/function/return.function.php | 18 -
02.php/webman/app/functions.php | 4 -
02.php/webman/app/middleware/StaticFile.php | 42 -
02.php/webman/app/model/Test.php | 29 -
02.php/webman/app/service/SVNAdmin/README.md | 0
02.php/webman/app/service/shell.service.php | 39 -
02.php/webman/app/view/index/view.html | 14 -
02.php/webman/composer.json | 57 -
02.php/webman/composer.lock | 624 --
02.php/webman/config/app.php | 24 -
02.php/webman/config/autoload.php | 48 -
02.php/webman/config/bootstrap.php | 18 -
02.php/webman/config/container.php | 15 -
02.php/webman/config/database.php | 15 -
02.php/webman/config/dependence.php | 15 -
02.php/webman/config/exception.php | 17 -
02.php/webman/config/log.php | 32 -
02.php/webman/config/middleware.php | 15 -
.../config/plugin/webman/action-hook/app.php | 4 -
.../plugin/webman/action-hook/middleware.php | 21 -
.../webman/config/plugin/webman/medoo/app.php | 4 -
.../config/plugin/webman/medoo/database.php | 39 -
02.php/webman/config/process.php | 37 -
02.php/webman/config/redis.php | 22 -
02.php/webman/config/route.php | 18 -
02.php/webman/config/server.php | 31 -
02.php/webman/config/session.php | 59 -
02.php/webman/config/static.php | 23 -
02.php/webman/config/svnadmin_router.php | 48 -
02.php/webman/config/svnadmin_subversion.php | 85 -
02.php/webman/config/translation.php | 25 -
02.php/webman/config/view.php | 22 -
02.php/webman/process/Monitor.php | 189 -
02.php/webman/public/404.html | 12 -
02.php/webman/public/favicon.ico | Bin 4286 -> 0 bytes
02.php/webman/runtime/.gitignore | 4 -
02.php/webman/runtime/logs/.gitignore | 2 -
02.php/webman/runtime/views/.gitignore | 2 -
02.php/webman/start.php | 112 -
02.php/webman/support/Plugin.php | 55 -
02.php/webman/support/Request.php | 24 -
02.php/webman/support/Response.php | 24 -
02.php/webman/support/bootstrap.php | 90 -
02.php/webman/support/helpers.php | 480 --
02.php/webman/windows.bat | 3 -
02.php/webman/windows.php | 104 -
177 files changed, 13282 insertions(+), 3543 deletions(-)
create mode 100644 02.php/api.php
create mode 100644 02.php/app/controller/Common.php
create mode 100644 02.php/app/controller/Logs.php
create mode 100644 02.php/app/controller/Mail.php
create mode 100644 02.php/app/controller/Personal.php
create mode 100644 02.php/app/controller/Safe.php
create mode 100644 02.php/app/controller/Statistics.php
create mode 100644 02.php/app/controller/Svn.php
create mode 100644 02.php/app/controller/Svngroup.php
create mode 100644 02.php/app/controller/Svnrep.php
create mode 100644 02.php/app/controller/Svnuser.php
create mode 100644 02.php/app/controller/Update.php
create mode 100644 02.php/app/controller/base/Base.php
rename 02.php/{webman/app/function/array.function.php => app/function/array.php} (98%)
rename 02.php/{webman/app/function/color.function.php => app/function/color.php} (100%)
rename 02.php/{webman/app/function/curl.function.php => app/function/curl.php} (97%)
rename 02.php/{webman/app/function/file.function.php => app/function/file.php} (98%)
create mode 100644 02.php/app/function/ipc.php
rename 02.php/{webman/app/function/json.function.php => app/function/json.php} (100%)
create mode 100644 02.php/app/function/message.php
rename 02.php/{webman/app/function/string.function.php => app/function/string.php} (100%)
rename 02.php/{webman/app/function/update.function.php => app/function/update.php} (100%)
rename 02.php/{webman/app/controller/Unimportant.php => app/service/Common.php} (86%)
rename 02.php/{webman/app/controller => app/service}/Logs.php (73%)
rename 02.php/{webman/app/controller => app/service}/Mail.php (94%)
rename 02.php/{webman/app/controller => app/service}/Personal.php (88%)
create mode 100644 02.php/app/service/Safe.php
rename 02.php/{webman/app/controller => app/service}/Statistics.php (85%)
rename 02.php/{webman/app/controller => app/service}/Svn.php (53%)
rename 02.php/{webman/app/controller => app/service}/Svngroup.php (86%)
rename 02.php/{webman/app/controller => app/service}/Svnrep.php (87%)
rename 02.php/{webman/app/controller => app/service}/Svnuser.php (70%)
rename 02.php/{webman/app/controller => app/service}/Update.php (54%)
create mode 100644 02.php/app/service/base/Base.php
rename 02.php/{webman/app/service/check.service.php => app/util/Check.php} (73%)
create mode 100644 02.php/app/util/Config.php
rename 02.php/{webman/app/service/SVNAdmin/src/core/Core.class.php => app/util/SVNAdmin/Core.php} (97%)
rename 02.php/{webman/app/service/SVNAdmin/src/class/Group.class.php => app/util/SVNAdmin/Group.php} (99%)
rename 02.php/{webman/app/service/SVNAdmin/src/class/Rep.class.php => app/util/SVNAdmin/Rep.php} (94%)
rename 02.php/{webman/app/service/SVNAdmin/src/class/User.class.php => app/util/SVNAdmin/User.php} (99%)
create mode 100644 02.php/config/daemon.php
create mode 100644 02.php/config/database.php
rename 02.php/{webman/config/svnadmin_reg.php => config/reg.php} (100%)
create mode 100644 02.php/config/router.php
rename 02.php/{webman/config/svnadmin_sign.php => config/sign.php} (100%)
rename 02.php/{webman/config/svnadmin_svn.php => config/svn.php} (90%)
rename 02.php/{webman/config/svnadmin_update.php => config/update.php} (59%)
rename 02.php/{webman/config/svnadmin_version.php => config/version.php} (100%)
create mode 100644 02.php/extension/Medoo-1.7.10/src/Medoo.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-af.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ar.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-az.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ba.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-be.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-bg.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ca.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ch.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-cs.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-da.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-de.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-el.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-eo.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-es.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-et.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fa.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fi.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fo.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fr.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-gl.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-he.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hi.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hr.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hu.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hy.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-id.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-it.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ja.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ka.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ko.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lt.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lv.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-mg.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ms.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-nb.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-nl.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pl.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pt.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pt_br.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ro.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ru.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sk.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sl.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr_latn.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sv.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tl.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tr.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-uk.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-vi.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh_cn.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/src/Exception.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/src/OAuth.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/src/OAuthTokenProvider.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/src/PHPMailer.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/src/POP3.php
create mode 100644 02.php/extension/PHPMailer-6.6.0/src/SMTP.php
rename 02.php/{webman/app/service/download.service.php => extension/Transfer/Transfer.php} (99%)
rename 02.php/{webman/app/service/verifycode.service.php => extension/Verifycode/Verifycode.php} (97%)
create mode 100644 02.php/server/svnadmind.php
create mode 100644 02.php/templete/svnserve/authz
create mode 100644 02.php/templete/svnserve/passwd
create mode 100644 02.php/templete/svnserve/servers
create mode 100644 02.php/templete/svnserve/svnserve
create mode 100644 02.php/templete/svnserve/svnserve.conf
delete mode 100644 02.php/webman/.gitignore
delete mode 100644 02.php/webman/LICENSE
delete mode 100644 02.php/webman/README.md
delete mode 100644 02.php/webman/app/controller/Core.php
delete mode 100644 02.php/webman/app/controller/Index.php
delete mode 100644 02.php/webman/app/controller/Safe.php
delete mode 100644 02.php/webman/app/function/return.function.php
delete mode 100644 02.php/webman/app/functions.php
delete mode 100644 02.php/webman/app/middleware/StaticFile.php
delete mode 100644 02.php/webman/app/model/Test.php
delete mode 100644 02.php/webman/app/service/SVNAdmin/README.md
delete mode 100644 02.php/webman/app/service/shell.service.php
delete mode 100644 02.php/webman/app/view/index/view.html
delete mode 100644 02.php/webman/composer.json
delete mode 100644 02.php/webman/composer.lock
delete mode 100644 02.php/webman/config/app.php
delete mode 100644 02.php/webman/config/autoload.php
delete mode 100644 02.php/webman/config/bootstrap.php
delete mode 100644 02.php/webman/config/container.php
delete mode 100644 02.php/webman/config/database.php
delete mode 100644 02.php/webman/config/dependence.php
delete mode 100644 02.php/webman/config/exception.php
delete mode 100644 02.php/webman/config/log.php
delete mode 100644 02.php/webman/config/middleware.php
delete mode 100644 02.php/webman/config/plugin/webman/action-hook/app.php
delete mode 100644 02.php/webman/config/plugin/webman/action-hook/middleware.php
delete mode 100644 02.php/webman/config/plugin/webman/medoo/app.php
delete mode 100644 02.php/webman/config/plugin/webman/medoo/database.php
delete mode 100644 02.php/webman/config/process.php
delete mode 100644 02.php/webman/config/redis.php
delete mode 100644 02.php/webman/config/route.php
delete mode 100644 02.php/webman/config/server.php
delete mode 100644 02.php/webman/config/session.php
delete mode 100644 02.php/webman/config/static.php
delete mode 100644 02.php/webman/config/svnadmin_router.php
delete mode 100644 02.php/webman/config/svnadmin_subversion.php
delete mode 100644 02.php/webman/config/translation.php
delete mode 100644 02.php/webman/config/view.php
delete mode 100644 02.php/webman/process/Monitor.php
delete mode 100644 02.php/webman/public/404.html
delete mode 100644 02.php/webman/public/favicon.ico
delete mode 100644 02.php/webman/runtime/.gitignore
delete mode 100644 02.php/webman/runtime/logs/.gitignore
delete mode 100644 02.php/webman/runtime/views/.gitignore
delete mode 100644 02.php/webman/start.php
delete mode 100644 02.php/webman/support/Plugin.php
delete mode 100644 02.php/webman/support/Request.php
delete mode 100644 02.php/webman/support/Response.php
delete mode 100644 02.php/webman/support/bootstrap.php
delete mode 100644 02.php/webman/support/helpers.php
delete mode 100644 02.php/webman/windows.bat
delete mode 100644 02.php/webman/windows.php
diff --git a/01.web/src/views/advance/index.vue b/01.web/src/views/advance/index.vue
index 85680a7..05abe01 100644
--- a/01.web/src/views/advance/index.vue
+++ b/01.web/src/views/advance/index.vue
@@ -553,7 +553,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Svn/GetDetail?t=web", data)
+ .post("/api.php?c=Svn&a=GetDetail&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -612,7 +612,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Mail/GetEmail?t=web", data)
+ .post("/api.php?c=Mail&a=GetEmail&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -657,7 +657,7 @@ export default {
status: that.formMailSmtp.status,
};
that.$axios
- .post("/api/Mail/EditEmail?t=web", data)
+ .post("/api.php?c=Mail&a=EditEmail&t=web", data)
.then(function (response) {
that.loadingEditEmail = false;
var result = response.data;
@@ -692,7 +692,7 @@ export default {
from: that.formMailSmtp.from,
};
that.$axios
- .post("/api/Mail/SendTest?t=web", data)
+ .post("/api.php?c=Mail&a=SendTest&t=web", data)
.then(function (response) {
that.loadingSendTest = false;
var result = response.data;
@@ -715,7 +715,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Svn/GetConfig?t=web", data)
+ .post("/api.php?c=Svn&a=GetConfig&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -749,7 +749,7 @@ export default {
that.loadingSvnserveStart = true;
var data = {};
that.$axios
- .post("/api/Svn/Start?t=web", data)
+ .post("/api.php?c=Svn&a=Start&t=web", data)
.then(function (response) {
that.loadingSvnserveStart = false;
var result = response.data;
@@ -780,7 +780,7 @@ export default {
that.loadingSvnserveStop = true;
var data = {};
that.$axios
- .post("/api/Svn/Stop?t=web", data)
+ .post("/api.php?c=Svn&a=Stop&t=web", data)
.then(function (response) {
that.loadingSvnserveStop = false;
var result = response.data;
@@ -814,7 +814,7 @@ export default {
bindPort: that.tempBindPort,
};
that.$axios
- .post("/api/Svn/EditPort?t=web", data)
+ .post("/api.php?c=Svn&a=EditPort&t=web", data)
.then(function (response) {
that.loadingEditPort = false;
var result = response.data;
@@ -849,7 +849,7 @@ export default {
bindHost: that.tempBindHost,
};
that.$axios
- .post("/api/Svn/EditHost?t=web", data)
+ .post("/api.php?c=Svn&a=EditHost&t=web", data)
.then(function (response) {
that.loadingEditHost = false;
var result = response.data;
@@ -884,7 +884,7 @@ export default {
manageHost: that.tempManageHost,
};
that.$axios
- .post("/api/Svn/EditManageHost?t=web", data)
+ .post("/api.php?c=Svn&a=EditManageHost&t=web", data)
.then(function (response) {
that.loadingEditManageHost = false;
var result = response.data;
@@ -913,7 +913,7 @@ export default {
enable: value,
};
that.$axios
- .post("/api/Svn/EditEnable?t=web", data)
+ .post("/api.php?c=Svn&a=EditEnable&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/index/index.vue b/01.web/src/views/index/index.vue
index 7235708..69e217c 100644
--- a/01.web/src/views/index/index.vue
+++ b/01.web/src/views/index/index.vue
@@ -235,7 +235,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Statistics/GetDisk?t=web", data)
+ .post("/api.php?c=Statistics&a=GetDisk&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -257,7 +257,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Statistics/GetSystemStatus?t=web", data)
+ .post("/api.php?c=Statistics&a=GetSystemStatus&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -279,7 +279,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Statistics/GetSystemAnalysis?t=web", data)
+ .post("/api.php?c=Statistics&a=GetSystemAnalysis&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/layout/basicLayout/index.vue b/01.web/src/views/layout/basicLayout/index.vue
index 7898137..a35a2ed 100644
--- a/01.web/src/views/layout/basicLayout/index.vue
+++ b/01.web/src/views/layout/basicLayout/index.vue
@@ -140,7 +140,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Unimportant/Logout?t=web", data)
+ .post("/api.php?c=Common&a=Logout&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/login/index.vue b/01.web/src/views/login/index.vue
index 0650d2f..582ad2f 100644
--- a/01.web/src/views/login/index.vue
+++ b/01.web/src/views/login/index.vue
@@ -153,7 +153,7 @@ export default {
that.loadingGetVeryfyCode = "loading......";
var data = {};
that.$axios
- .post("/api/Unimportant/GetVeryfyCode?t=web", data)
+ .post("/api.php?c=Common&a=GetVeryfyCode&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -180,7 +180,7 @@ export default {
code: that.formUserLogin.code,
};
that.$axios
- .post("/api/Unimportant/Login?t=web", data)
+ .post("/api.php?c=Common&a=Login&t=web", data)
.then(function (response) {
that.loadingLogin = false;
var result = response.data;
diff --git a/01.web/src/views/personal/index.vue b/01.web/src/views/personal/index.vue
index 43dafea..675e032 100644
--- a/01.web/src/views/personal/index.vue
+++ b/01.web/src/views/personal/index.vue
@@ -182,7 +182,7 @@ export default {
confirm: that.formEditAdminUserName.confirm,
};
that.$axios
- .post("/api/Personal/EditAdminUserName?t=web", data)
+ .post("/api.php?c=Personal&a=EditAdminUserName&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -215,7 +215,7 @@ export default {
confirm: that.formEditAdminUserPass.confirm,
};
that.$axios
- .post("/api/Personal/EditAdminUserPass?t=web", data)
+ .post("/api.php?c=Personal&a=EditAdminUserPass&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -247,7 +247,7 @@ export default {
confirm: that.formEditSvnUserPass.confirm,
};
that.$axios
- .post("/api/Personal/EditSvnUserPass?t=web", data)
+ .post("/api.php?c=Personal&a=EditSvnUserPass&t=web", data)
.then(function (response) {
that.loadingEditSvnUserPass = false;
var result = response.data;
@@ -272,7 +272,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Unimportant/Logout?t=web", data)
+ .post("/api.php?c=Common&a=Logout&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/repositoryGroup/index.vue b/01.web/src/views/repositoryGroup/index.vue
index b91fd18..5aae3b5 100644
--- a/01.web/src/views/repositoryGroup/index.vue
+++ b/01.web/src/views/repositoryGroup/index.vue
@@ -381,7 +381,7 @@ export default {
sortType: that.sortType,
};
that.$axios
- .post("/api/Svngroup/GetGroupList?t=web", data)
+ .post("/api.php?c=Svngroup&a=GetGroupList&t=web", data)
.then(function (response) {
that.loadingGroup = false;
var result = response.data;
@@ -409,7 +409,7 @@ export default {
svn_group_note: that.tableGroupData[index].svn_group_note,
};
that.$axios
- .post("/api/Svngroup/EditGroupNote?t=web", data)
+ .post("/api.php?c=Svngroup&a=EditGroupNote&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -436,7 +436,7 @@ export default {
svn_group_name: that.formCreateGroup.svn_group_name,
};
that.$axios
- .post("/api/Svngroup/CreateGroup?t=web", data)
+ .post("/api.php?c=Svngroup&a=CreateGroup&t=web", data)
.then(function (response) {
that.loadingCreateGroup = false;
var result = response.data;
@@ -475,7 +475,7 @@ export default {
groupNameNew: that.formEditGroupName.groupNameNew,
};
that.$axios
- .post("/api/Svngroup/EditGroupName?t=web", data)
+ .post("/api.php?c=Svngroup&a=EditGroupName&t=web", data)
.then(function (response) {
that.loadingEditGroupName = false;
var result = response.data;
@@ -506,7 +506,7 @@ export default {
svn_group_name: svn_group_name,
};
that.$axios
- .post("/api/Svngroup/DelGroup?t=web", data)
+ .post("/api.php?c=Svngroup&a=DelGroup&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -549,7 +549,7 @@ export default {
svn_group_name: that.currentSelectGroupName,
};
that.$axios
- .post("/api/Svngroup/GetGroupMember?t=web", data)
+ .post("/api.php?c=Svngroup&a=GetGroupMember&t=web", data)
.then(function (response) {
that.loadingRepAllUser = false;
that.loadingRepAllGroup = false;
@@ -598,7 +598,7 @@ export default {
svn_user_name: userName,
};
that.$axios
- .post("/api/Svngroup/GroupAddUser?t=web", data)
+ .post("/api.php?c=Svngroup&a=GroupAddUser&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -624,7 +624,7 @@ export default {
svn_user_name: userName,
};
that.$axios
- .post("/api/Svngroup/GroupRemoveUser?t=web", data)
+ .post("/api.php?c=Svngroup&a=GroupRemoveUser&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -650,7 +650,7 @@ export default {
svn_group_name_add: groupName,
};
that.$axios
- .post("/api/Svngroup/GroupAddGroup?t=web", data)
+ .post("/api.php?c=Svngroup&a=GroupAddGroup&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -676,7 +676,7 @@ export default {
svn_group_name_del: groupName,
};
that.$axios
- .post("/api/Svngroup/GroupRemoveGroup?t=web", data)
+ .post("/api.php?c=Svngroup&a=GroupRemoveGroup&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/repositoryInfo/index.vue b/01.web/src/views/repositoryInfo/index.vue
index ad2c743..42742ef 100644
--- a/01.web/src/views/repositoryInfo/index.vue
+++ b/01.web/src/views/repositoryInfo/index.vue
@@ -462,7 +462,7 @@
multiple
:on-success="UploadSuccess"
:before-upload="BeforeUpload"
- action="/api/Svnrep/UploadBackup?t=web"
+ action="/api.php?c=Svnrep&a=UploadBackup&t=web"
name="file"
:headers="{ token: token }"
>
@@ -1089,7 +1089,7 @@ export default {
var that = this;
var data = {};
that.$axios
- .post("/api/Svn/GetStatus?t=web", data)
+ .post("/api.php?c=Svn&a=GetStatus&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -1119,7 +1119,7 @@ export default {
rep_type: that.formRepAdd.rep_type,
};
that.$axios
- .post("/api/Svnrep/CreateRep?t=web", data)
+ .post("/api.php?c=Svnrep&a=CreateRep&t=web", data)
.then(function (response) {
that.loadingCreateRep = false;
that.modalCreateRep = false;
@@ -1161,7 +1161,7 @@ export default {
sortType: that.sortType,
};
that.$axios
- .post("/api/Svnrep/GetRepList?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepList&t=web", data)
.then(function (response) {
that.loadingRep = false;
var result = response.data;
@@ -1221,7 +1221,7 @@ export default {
sortType: that.sortType,
};
that.$axios
- .post("/api/Svnrep/GetSvnUserRepList?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetSvnUserRepList&t=web", data)
.then(function (response) {
that.loadingUserRep = false;
var result = response.data;
@@ -1276,7 +1276,7 @@ export default {
rep_note: that.tableDataRep[index].rep_note,
};
that.$axios
- .post("/api/Svnrep/EditRepNote?t=web", data)
+ .post("/api.php?c=Svnrep&a=EditRepNote&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -1361,7 +1361,7 @@ export default {
var data = {};
return new Promise(function (resolve, reject) {
that.$axios
- .post("/api/Svn/GetCheckout?t=web", data)
+ .post("/api.php?c=Svn&a=GetCheckout&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -1390,7 +1390,7 @@ export default {
path: that.currentRepTreePath,
};
that.$axios
- .post("/api/Svnrep/GetRepCon?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepCon&t=web", data)
.then(function (response) {
that.loadingRepCon = false;
var result = response.data;
@@ -1425,7 +1425,7 @@ export default {
path: that.currentRepTreePath,
};
that.$axios
- .post("/api/Svnrep/GetUserRepCon?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetUserRepCon&t=web", data)
.then(function (response) {
that.loadingRepCon = false;
var result = response.data;
@@ -1510,7 +1510,7 @@ export default {
that.tableDataBackup = [];
var data = {};
that.$axios
- .post("/api/Svnrep/GetBackupList?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetBackupList&t=web", data)
.then(function (response) {
that.loadingRepBackupList = false;
var result = response.data;
@@ -1533,7 +1533,7 @@ export default {
rep_name: that.currentRepName,
};
that.$axios
- .post("/api/Svnrep/RepDump?t=web", data)
+ .post("/api.php?c=Svnrep&a=RepDump&t=web", data)
.then(function (response) {
that.loadingRepDump = false;
var result = response.data;
@@ -1556,7 +1556,7 @@ export default {
DownloadRepBackup(fileName) {
var that = this;
const streamSaver = require("../../libs/streamsaver/StreamSaver");
- fetch("/api/Svnrep/DownloadRepBackup?t=web", {
+ fetch("/api.php?c=Svnrep&a=DownloadRepBackup&t=web", {
headers: {
"Content-Type": "application/json",
token: that.token,
@@ -1575,7 +1575,9 @@ export default {
window.WritableStream = WritableStream;
}
- const fileStream = streamSaver.createWriteStream(fileName);
+ const fileStream = streamSaver.createWriteStream(fileName, {
+ size: response.headers.get("content-length"),
+ });
const readableStream = response.body;
// More optimized
@@ -1596,6 +1598,80 @@ export default {
pump();
});
},
+ DownloadRepBackup2(fileName) {
+ var that = this;
+ const streamSaver = require("../../libs/streamsaver/StreamSaver");
+ fetch("https://download.witersen.com/test/examples/api.php", {
+ headers: {
+ "Content-Type": "application/json",
+ },
+ method: "POST",
+ body: JSON.stringify({
+ fileName: fileName,
+ }),
+ }).then((response) => {
+ // These code section is adapted from an example of the StreamSaver.js
+ // https://jimmywarting.github.io/StreamSaver.js/examples/fetch.html
+
+ // If the WritableStream is not available (Firefox, Safari), take it from the ponyfill
+ if (!window.WritableStream) {
+ streamSaver.WritableStream = WritableStream;
+ window.WritableStream = WritableStream;
+ }
+
+ const fileStream = streamSaver.createWriteStream(fileName, {
+ size: response.headers.get("content-length"),
+ });
+ const readableStream = response.body;
+
+ // More optimized
+ if (readableStream.pipeTo) {
+ return readableStream.pipeTo(fileStream);
+ }
+
+ window.writer = fileStream.getWriter();
+
+ const reader = response.body.getReader();
+ const pump = () =>
+ reader
+ .read()
+ .then((res) =>
+ res.done ? writer.close() : writer.write(res.value).then(pump)
+ );
+
+ pump();
+ });
+ },
+ DownloadRepBackup3(fileName) {
+ var that = this;
+ var data = {
+ fileName: fileName,
+ };
+ that.$axios.setAttribute;
+ that.$axios
+ .post("/api.php?c=Svnrep&a=DownloadRepBackup&t=web", data, {
+ responseType: "blob",
+ })
+ .then(function (response) {
+ let url = window.URL.createObjectURL(
+ new Blob([response.data], { type: "application/octet-stream" })
+ );
+ let link = document.createElement("a");
+ link.style.display = "none";
+ link.href = url;
+ link.setAttribute("download", fileName);
+ document.body.appendChild(link);
+ link.click();
+ //释放url对象所占资源
+ window.URL.revokeObjectURL(url);
+ //用完删除
+ document.body.removeChild(link);
+ })
+ .catch(function (error) {
+ console.log(error);
+ that.$Message.error("出错了 请联系管理员!");
+ });
+ },
/**
* 删除备份文件
*/
@@ -1609,7 +1685,7 @@ export default {
fileName: fileName,
};
that.$axios
- .post("/api/Svnrep/DelRepBackup?t=web", data)
+ .post("/api.php?c=Svnrep&a=DelRepBackup&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -1670,7 +1746,7 @@ export default {
};
return new Promise(function (resolve, reject) {
that.$axios
- .post("/api/Svnrep/GetRepTree?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepTree&t=web", data)
.then(function (response) {
resolve(response);
})
@@ -1760,7 +1836,7 @@ export default {
path: that.currentRepTreePriPath,
};
that.$axios
- .post("/api/Svnrep/GetRepPathUserPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepPathUserPri&t=web", data)
.then(function (response) {
that.loadingRepPathUserPri = false;
var result = response.data;
@@ -1818,7 +1894,7 @@ export default {
user: that.currentRepPriUser,
};
that.$axios
- .post("/api/Svnrep/DelRepPathUserPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=DelRepPathUserPri&t=web", data)
.then(function (response) {
that.loadingDelRepPathUserPri = false;
var result = response.data;
@@ -1853,7 +1929,7 @@ export default {
.userName,
};
that.$axios
- .post("/api/Svnrep/EditRepPathUserPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=EditRepPathUserPri&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -1880,7 +1956,7 @@ export default {
user: that.currentRepPriAddUser,
};
that.$axios
- .post("/api/Svnrep/AddRepPathUserPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=AddRepPathUserPri&t=web", data)
.then(function (response) {
that.modalRepAllUser = false;
var result = response.data;
@@ -1916,7 +1992,7 @@ export default {
that.loadingAllUserList = true;
var data = {};
that.$axios
- .post("/api/Svnuser/GetAllUserList?t=web", data)
+ .post("/api.php?c=Svnuser&a=GetAllUserList&t=web", data)
.then(function (response) {
that.loadingAllUserList = false;
var result = response.data;
@@ -1956,7 +2032,7 @@ export default {
path: that.currentRepTreePriPath,
};
that.$axios
- .post("/api/Svnrep/GetRepPathGroupPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepPathGroupPri&t=web", data)
.then(function (response) {
that.loadingRepPathGroupPri = false;
var result = response.data;
@@ -2018,7 +2094,7 @@ export default {
group: that.currentRepPriGroup,
};
that.$axios
- .post("/api/Svnrep/DelRepPathGroupPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=DelRepPathGroupPri&t=web", data)
.then(function (response) {
that.loadingDelRepPathGroupPri = false;
var result = response.data;
@@ -2054,7 +2130,7 @@ export default {
that.tableDataRepPathGroupPri[that.currentRepPriGroupIndex].groupName,
};
that.$axios
- .post("/api/Svnrep/EditRepPathGroupPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=EditRepPathGroupPri&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -2081,7 +2157,7 @@ export default {
group: that.currentRepPriAddGroup,
};
that.$axios
- .post("/api/Svnrep/AddRepPathGroupPri?t=web", data)
+ .post("/api.php?c=Svnrep&a=AddRepPathGroupPri&t=web", data)
.then(function (response) {
that.modalRepAllGroup = false;
var result = response.data;
@@ -2117,7 +2193,7 @@ export default {
that.loadingAllGroupList = true;
var data = {};
that.$axios
- .post("/api/Svngroup/GetAllGroupList?t=web", data)
+ .post("/api.php?c=Svngroup&a=GetAllGroupList&t=web", data)
.then(function (response) {
that.loadingAllGroupList = false;
var result = response.data;
@@ -2162,7 +2238,7 @@ export default {
rep_name: that.currentRepName,
};
that.$axios
- .post("/api/Svnrep/GetRepHooks?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepHooks&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -2187,7 +2263,7 @@ export default {
content: that.formRepHooks.type[that.formRepHooks.select].shell,
};
that.$axios
- .post("/api/Svnrep/EditRepHook?t=web", data)
+ .post("/api.php?c=Svnrep&a=EditRepHook&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -2230,7 +2306,7 @@ export default {
rep_name: that.currentRepName,
};
that.$axios
- .post("/api/Svnrep/GetRepDetail?t=web", data)
+ .post("/api.php?c=Svnrep&a=GetRepDetail&t=web", data)
.then(function (response) {
that.loadingRepDetail = false;
var result = response.data;
@@ -2307,7 +2383,7 @@ export default {
fileName: that.formUploadBackup.fileName,
};
that.$axios
- .post("/api/Svnrep/ImportRep?t=web", data)
+ .post("/api.php?c=Svnrep&a=ImportRep&t=web", data)
.then(function (response) {
that.loadingImportBackup = false;
var result = response.data;
@@ -2347,7 +2423,7 @@ export default {
new_rep_name: that.formRepEdit.new_rep_name,
};
that.$axios
- .post("/api/Svnrep/EditRepName?t=web", data)
+ .post("/api.php?c=Svnrep&a=EditRepName&t=web", data)
.then(function (response) {
that.loadingEditRepName = false;
var result = response.data;
@@ -2380,7 +2456,7 @@ export default {
rep_name: rep_name,
};
that.$axios
- .post("/api/Svnrep/DelRep?t=web", data)
+ .post("/api.php?c=Svnrep&a=DelRep&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/repositoryUser/index.vue b/01.web/src/views/repositoryUser/index.vue
index c1ccdc1..59994eb 100644
--- a/01.web/src/views/repositoryUser/index.vue
+++ b/01.web/src/views/repositoryUser/index.vue
@@ -292,7 +292,7 @@ export default {
sortType: that.sortType,
};
that.$axios
- .post("/api/Svnuser/GetUserList?t=web", data)
+ .post("/api.php?c=Svnuser&a=GetUserList&t=web", data)
.then(function (response) {
that.loadingUser = false;
var result = response.data;
@@ -329,7 +329,7 @@ export default {
svn_user_name: svn_user_name,
};
that.$axios
- .post("/api/Svnuser/EnableUser?t=web", data)
+ .post("/api.php?c=Svnuser&a=EnableUser&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -352,7 +352,7 @@ export default {
svn_user_name: svn_user_name,
};
that.$axios
- .post("/api/Svnuser/DisableUser?t=web", data)
+ .post("/api.php?c=Svnuser&a=DisableUser&t=web", data)
.then(function (response) {
that.loadingUser = false;
var result = response.data;
@@ -377,7 +377,7 @@ export default {
svn_user_note: that.tableDataUser[index].svn_user_note,
};
that.$axios
- .post("/api/Svnuser/EditUserNote?t=web", data)
+ .post("/api.php?c=Svnuser&a=EditUserNote&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@@ -415,7 +415,7 @@ export default {
svn_user_pass: that.formCreateUser.svn_user_pass,
};
that.$axios
- .post("/api/Svnuser/CreateUser?t=web", data)
+ .post("/api.php?c=Svnuser&a=CreateUser&t=web", data)
.then(function (response) {
that.loadingCreateUser = false;
var result = response.data;
@@ -458,7 +458,7 @@ export default {
that.tableDataUser[that.formEditUser.index].svn_user_status,
};
that.$axios
- .post("/api/Svnuser/EditUserPass?t=web", data)
+ .post("/api.php?c=Svnuser&a=EditUserPass&t=web", data)
.then(function (response) {
that.loadingEditUserPass = false;
var result = response.data;
@@ -491,7 +491,7 @@ export default {
svn_user_status: that.tableDataUser[index].svn_user_status,
};
that.$axios
- .post("/api/Svnuser/DelUser?t=web", data)
+ .post("/api.php?c=Svnuser&a=DelUser&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
diff --git a/01.web/src/views/systemLog/index.vue b/01.web/src/views/systemLog/index.vue
index c080b3f..115ad1d 100644
--- a/01.web/src/views/systemLog/index.vue
+++ b/01.web/src/views/systemLog/index.vue
@@ -163,7 +163,7 @@ export default {
searchKeyword: that.searchKeywordLog,
};
that.$axios
- .post("/api/Logs/GetLogList?t=web", data)
+ .post("/api.php?c=Logs&a=GetLogList&t=web", data)
.then(function (response) {
that.loadingGetLogList = false;
var result = response.data;
@@ -193,7 +193,7 @@ export default {
that.loadingClearLogs = true;
var data = {};
that.$axios
- .post("/api/Logs/ClearLogs?t=web", data)
+ .post("/api.php?c=Logs&a=ClearLogs&t=web", data)
.then(function (response) {
that.loadingClearLogs = false;
var result = response.data;
diff --git a/01.web/webpack.dev.config.js b/01.web/webpack.dev.config.js
index b8515ea..9821745 100644
--- a/01.web/webpack.dev.config.js
+++ b/01.web/webpack.dev.config.js
@@ -45,10 +45,10 @@ module.exports = merge(webpackBaseConfig, {
hotOnly: false,
disableHostCheck: true,
proxy: {
- '/api': {
- target: 'http://workman.witersen.com:8787',
+ '/api.php': {
+ target: 'http://workman.witersen.com/api.php',
changeOrigin: true,
- pathRewrite: { '^/api': '' }
+ // pathRewrite: { '^/api': '' }
}
}
}
diff --git a/02.php/api.php b/02.php/api.php
new file mode 100644
index 0000000..09a4352
--- /dev/null
+++ b/02.php/api.php
@@ -0,0 +1,92 @@
+$action();
+ } else {
+ json1(401, 0, '无效的方法名');
+ }
+} else {
+ json1(401, 0, '无效的控制器名');
+}
diff --git a/02.php/app/controller/Common.php b/02.php/app/controller/Common.php
new file mode 100644
index 0000000..38015fc
--- /dev/null
+++ b/02.php/app/controller/Common.php
@@ -0,0 +1,60 @@
+ServiceCommon = new ServiceCommon();
+ }
+
+ /**
+ * 登录
+ */
+ public function Login()
+ {
+ $result = $this->ServiceCommon->Login();
+ json2($result);
+ }
+
+ /**
+ * 注销
+ *
+ * 注销操作为将用户尚未过期的token加入所谓黑名单
+ * 每次注销触发主动扫描黑名单 将名单中过期的token删除
+ * 目的:实现用户注销后尚未过期的token无法继续使用
+ */
+ public function Logout()
+ {
+ $this->ServiceCommon->Logout();
+ json2();
+ }
+
+ /**
+ * 获取验证码
+ */
+ public function GetVeryfyCode()
+ {
+ $result = $this->ServiceCommon->GetVeryfyCode();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Logs.php b/02.php/app/controller/Logs.php
new file mode 100644
index 0000000..26e2113
--- /dev/null
+++ b/02.php/app/controller/Logs.php
@@ -0,0 +1,47 @@
+ServiceLogs = new ServiceLogs();
+ }
+
+ /**
+ * 获取日志列表
+ */
+ public function GetLogList()
+ {
+ $result = $this->ServiceLogs->GetLogList();
+ json2($result);
+ }
+
+ /**
+ * 清空日志
+ */
+ public function ClearLogs()
+ {
+ $result = $this->ServiceLogs->ClearLogs();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Mail.php b/02.php/app/controller/Mail.php
new file mode 100644
index 0000000..f2ba8ee
--- /dev/null
+++ b/02.php/app/controller/Mail.php
@@ -0,0 +1,56 @@
+ServiceMail = new ServiceMail();
+ }
+
+ /**
+ * 获取邮件配置信息
+ */
+ public function GetEmail()
+ {
+ $result = $this->ServiceMail->GetEmail();
+ json2($result);
+ }
+
+ /**
+ * 修改邮件配置信息
+ */
+ public function EditEmail()
+ {
+ $this->ServiceMail->EditEmail();
+ json2();
+ }
+
+ /**
+ * 发送测试邮件
+ */
+ public function SendTest()
+ {
+ $result = $this->ServiceMail->SendTest();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Personal.php b/02.php/app/controller/Personal.php
new file mode 100644
index 0000000..e0376ad
--- /dev/null
+++ b/02.php/app/controller/Personal.php
@@ -0,0 +1,56 @@
+ServicePersonal = new ServicePersonal();
+ }
+
+ /**
+ * 管理人员修改自己的账号
+ */
+ public function EditAdminUserName()
+ {
+ $result = $this->ServicePersonal->EditAdminUserName();
+ json2($result);
+ }
+
+ /**
+ * 管理人员修改自己的密码
+ */
+ public function EditAdminUserPass()
+ {
+ $result = $this->ServicePersonal->EditAdminUserPass();
+ json2($result);
+ }
+
+ /**
+ * SVN用户修改自己的密码
+ */
+ public function EditSvnUserPass()
+ {
+ $result = $this->ServicePersonal->EditSvnUserPass();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Safe.php b/02.php/app/controller/Safe.php
new file mode 100644
index 0000000..d7126d5
--- /dev/null
+++ b/02.php/app/controller/Safe.php
@@ -0,0 +1,29 @@
+ServiceSafe = new ServiceSafe();
+ }
+}
diff --git a/02.php/app/controller/Statistics.php b/02.php/app/controller/Statistics.php
new file mode 100644
index 0000000..8ab205d
--- /dev/null
+++ b/02.php/app/controller/Statistics.php
@@ -0,0 +1,70 @@
+ServiceStatistics = new ServiceStatistics();
+ }
+
+ /**
+ * 获取状态
+ *
+ * 负载状态
+ * CPU使用率
+ * 内存使用率
+ */
+ public function GetSystemStatus()
+ {
+ $result = $this->ServiceStatistics->GetSystemStatus();
+ json2($result);
+ }
+
+ /**
+ * 获取硬盘
+ *
+ * 获取硬盘数量和每个硬盘的详细信息
+ */
+ public function GetDisk()
+ {
+ $result = $this->ServiceStatistics->GetDisk();
+ json2($result);
+ }
+
+ /**
+ * 获取统计
+ *
+ * 操作系统类型
+ * 仓库占用体积
+ * SVN仓库数量
+ * SVN用户数量
+ * SVN分组数量
+ * 计划任务数量
+ * 运行日志数量
+ */
+ public function GetSystemAnalysis()
+ {
+ $result = $this->ServiceStatistics->GetSystemAnalysis();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Svn.php b/02.php/app/controller/Svn.php
new file mode 100644
index 0000000..6015a03
--- /dev/null
+++ b/02.php/app/controller/Svn.php
@@ -0,0 +1,140 @@
+ServiceSvn = new ServiceSvn();
+ }
+
+ /**
+ * 获取Subversion运行状态 用于页头提醒
+ */
+ public function GetStatus()
+ {
+ $result = $this->ServiceSvn->GetStatus();
+ json2($result);
+ }
+
+ /**
+ * 获取Subversion的检出地址前缀
+ *
+ * 先从Subversion配置文件获取绑定端口和主机
+ * 然后与listen.json配置文件中的端口和主机进行对比和同步
+ */
+ public function GetCheckout()
+ {
+ $result = $this->ServiceSvn->GetCheckout();
+ json2($result);
+ }
+
+ /**
+ * 获取Subversion的详细信息
+ */
+ public function GetDetail()
+ {
+ $result = $this->ServiceSvn->GetDetail();
+ json2($result);
+ }
+
+ /**
+ * 安装SVN
+ */
+ public function Install()
+ {
+ $result = $this->ServiceSvn->Install();
+ json2($result);
+ }
+
+ /**
+ * 卸载SVN
+ */
+ public function UnInstall()
+ {
+ $result = $this->ServiceSvn->UnInstall();
+ json2($result);
+ }
+
+ /**
+ * 启动SVN
+ */
+ public function Start()
+ {
+ $result = $this->ServiceSvn->Start();
+ json2($result);
+ }
+
+ /**
+ * 停止SVN
+ */
+ public function Stop()
+ {
+ $result = $this->ServiceSvn->Stop();
+ json2($result);
+ }
+
+ /**
+ * 修改svnserve的绑定端口
+ */
+ public function EditPort()
+ {
+ $result = $this->ServiceSvn->EditPort();
+ json2($result);
+ }
+
+ /**
+ * 修改svnserve的绑定主机
+ */
+ public function EditHost()
+ {
+ $result = $this->ServiceSvn->EditHost();
+ json2($result);
+ }
+
+ /**
+ * 修改管理系统主机名
+ */
+ public function EditManageHost()
+ {
+ $result = $this->ServiceSvn->EditManageHost();
+ json2($result);
+ }
+
+ /**
+ * 修改检出地址
+ */
+ public function EditEnable()
+ {
+ $result = $this->ServiceSvn->EditEnable();
+ json2($result);
+ }
+
+ /**
+ * 获取配置文件列表
+ */
+ public function GetConfig()
+ {
+ $result = $this->ServiceSvn->GetConfig();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Svngroup.php b/02.php/app/controller/Svngroup.php
new file mode 100644
index 0000000..fa27071
--- /dev/null
+++ b/02.php/app/controller/Svngroup.php
@@ -0,0 +1,128 @@
+ServiceSvngroup = new ServiceSvngroup();
+ }
+
+ /**
+ * 获取所有的分组列表
+ */
+ public function GetAllGroupList()
+ {
+ $result = $this->ServiceSvngroup->GetAllGroupList();
+ json2($result);
+ }
+
+ /**
+ * 获取带有分页的分组列表
+ */
+ public function GetGroupList()
+ {
+ $result = $this->ServiceSvngroup->GetGroupList();
+ json2($result);
+ }
+
+ /**
+ * 编辑分组备注信息
+ */
+ public function EditGroupNote()
+ {
+ $result = $this->ServiceSvngroup->EditGroupNote();
+ json2($result);
+ }
+
+ /**
+ * 新建SVN分组
+ */
+ public function CreateGroup()
+ {
+ $result = $this->ServiceSvngroup->CreateGroup();
+ json2($result);
+ }
+
+ /**
+ * 删除SVN分组
+ */
+ public function DelGroup()
+ {
+ $result = $this->ServiceSvngroup->DelGroup();
+ json2($result);
+ }
+
+ /**
+ * 修改SVN分组的名称
+ */
+ public function EditGroupName()
+ {
+ $result = $this->ServiceSvngroup->EditGroupName();
+ json2($result);
+ }
+
+ /**
+ * 获取SVN分组的用户成员和分组成员
+ */
+ public function GetGroupMember()
+ {
+ $result = $this->ServiceSvngroup->GetGroupMember();
+ json2($result);
+ }
+
+ /**
+ * 将用户添加为SVN分组的成员
+ */
+ public function GroupAddUser()
+ {
+ $result = $this->ServiceSvngroup->GroupAddUser();
+ json2($result);
+ }
+
+ /**
+ * 将用户从SVN分组的成员移除
+ */
+ public function GroupRemoveUser()
+ {
+ $result = $this->ServiceSvngroup->GroupRemoveUser();
+ json2($result);
+ }
+
+ /**
+ * 将分组添加为SVN分组的成员
+ */
+ public function GroupAddGroup()
+ {
+ $result = $this->ServiceSvngroup->GroupAddGroup();
+ json2($result);
+ }
+
+ /**
+ * 将分组从SVN分组的成员移除
+ */
+ public function GroupRemoveGroup()
+ {
+ $result = $this->ServiceSvngroup->GroupRemoveGroup();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Svnrep.php b/02.php/app/controller/Svnrep.php
new file mode 100644
index 0000000..70ae011
--- /dev/null
+++ b/02.php/app/controller/Svnrep.php
@@ -0,0 +1,264 @@
+ServiceSvnrep = new ServiceSvnrep();
+ }
+
+ /**
+ * 新建仓库
+ */
+ public function CreateRep()
+ {
+ $result = $this->ServiceSvnrep->CreateRep();
+ json2($result);
+ }
+
+ /**
+ * 获取仓库列表
+ */
+ public function GetRepList()
+ {
+ $result = $this->ServiceSvnrep->GetRepList();
+ json2($result);
+ }
+
+ /**
+ * SVN用户获取自己有权限的仓库列表
+ */
+ public function GetSvnUserRepList()
+ {
+ $result = $this->ServiceSvnrep->GetSvnUserRepList();
+ json2($result);
+ }
+
+ /**
+ * 修改仓库的备注信息
+ */
+ public function EditRepNote()
+ {
+ $result = $this->ServiceSvnrep->EditRepNote();
+ json2($result);
+ }
+
+ /**
+ * SVN用户根据目录名称获取该目录下的文件和文件夹列表
+ */
+ public function GetUserRepCon()
+ {
+ $result = $this->ServiceSvnrep->GetUserRepCon();
+ json2($result);
+ }
+
+ /**
+ * 管理人员根据目录名称获取该目录下的文件和文件夹列表
+ */
+ public function GetRepCon()
+ {
+ $result = $this->ServiceSvnrep->GetRepCon();
+ json2($result);
+ }
+
+ /**
+ * 根据目录名称获取该目录下的目录树
+ *
+ * 管理员配置目录授权用
+ */
+ public function GetRepTree()
+ {
+ $result = $this->ServiceSvnrep->GetRepTree();
+ json2($result);
+ }
+
+ /**
+ * 获取某个仓库路径的用户权限列表
+ */
+ public function GetRepPathUserPri()
+ {
+ $result = $this->ServiceSvnrep->GetRepPathUserPri();
+ json2($result);
+ }
+
+ /**
+ * 获取某个仓库路径的分组权限列表
+ */
+ public function GetRepPathGroupPri()
+ {
+ $result = $this->ServiceSvnrep->GetRepPathGroupPri();
+ json2($result);
+ }
+
+ /**
+ * 增加某个仓库路径的用户权限
+ */
+ public function AddRepPathUserPri()
+ {
+ $result = $this->ServiceSvnrep->AddRepPathUserPri();
+ json2($result);
+ }
+
+ /**
+ * 删除某个仓库路径的用户权限
+ */
+ public function DelRepPathUserPri()
+ {
+ $result = $this->ServiceSvnrep->DelRepPathUserPri();
+ json2($result);
+ }
+
+ /**
+ * 修改某个仓库路径的用户权限
+ */
+ public function EditRepPathUserPri()
+ {
+ $result = $this->ServiceSvnrep->EditRepPathUserPri();
+ json2($result);
+ }
+
+ /**
+ * 增加某个仓库路径的分组权限
+ */
+ public function AddRepPathGroupPri()
+ {
+ $result = $this->ServiceSvnrep->AddRepPathGroupPri();
+ json2($result);
+ }
+
+ /**
+ * 删除某个仓库路径的分组权限
+ */
+ public function DelRepPathGroupPri()
+ {
+ $result = $this->ServiceSvnrep->DelRepPathGroupPri();
+ json2($result);
+ }
+
+ /**
+ * 修改某个仓库路径的分组权限
+ */
+ public function EditRepPathGroupPri()
+ {
+ $result = $this->ServiceSvnrep->EditRepPathGroupPri();
+ json2($result);
+ }
+
+ /**
+ * 修改仓库名称
+ */
+ public function EditRepName()
+ {
+ $result = $this->ServiceSvnrep->EditRepName();
+ json2($result);
+ }
+
+ /**
+ * 删除仓库
+ */
+ public function DelRep()
+ {
+ $result = $this->ServiceSvnrep->DelRep();
+ json2($result);
+ }
+
+ /**
+ * 获取仓库的属性内容(key-value的形式)
+ */
+ public function GetRepDetail()
+ {
+ $result = $this->ServiceSvnrep->GetRepDetail();
+ json2($result);
+ }
+
+ /**
+ * 获取备份文件夹下的文件列表
+ */
+ public function GetBackupList()
+ {
+ $result = $this->ServiceSvnrep->GetBackupList();
+ json2($result);
+ }
+
+ /**
+ * 立即备份当前仓库
+ */
+ public function RepDump()
+ {
+ $result = $this->ServiceSvnrep->RepDump();
+ json2($result);
+ }
+
+ /**
+ * 删除备份文件
+ */
+ public function DelRepBackup()
+ {
+ $result = $this->ServiceSvnrep->DelRepBackup();
+ json2($result);
+ }
+
+ /**
+ * 下载备份文件
+ */
+ public function DownloadRepBackup()
+ {
+ $this->ServiceSvnrep->DownloadRepBackup();
+ }
+
+ /**
+ * 上传文件到备份文件夹
+ */
+ public function UploadBackup()
+ {
+ $result = $this->ServiceSvnrep->UploadBackup();
+ json2($result);
+ }
+
+ /**
+ * 从本地备份文件导入仓库
+ */
+ public function ImportRep()
+ {
+ $result = $this->ServiceSvnrep->ImportRep();
+ json2($result);
+ }
+
+ /**
+ * 获取仓库的钩子和对应的内容列表
+ */
+ public function GetRepHooks()
+ {
+ $result = $this->ServiceSvnrep->GetRepHooks();
+ json2($result);
+ }
+
+ /**
+ * 修改仓库的钩子内容(针对单个钩子)
+ */
+ public function EditRepHook()
+ {
+ $result = $this->ServiceSvnrep->EditRepHook();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Svnuser.php b/02.php/app/controller/Svnuser.php
new file mode 100644
index 0000000..8ebb5d9
--- /dev/null
+++ b/02.php/app/controller/Svnuser.php
@@ -0,0 +1,105 @@
+ServiceSvnuser = new ServiceSvnuser();
+ }
+
+ /**
+ * 获取全部的SVN用户
+ *
+ * 只包含用户名和启用状态
+ */
+ public function GetAllUserList()
+ {
+ $result = $this->ServiceSvnuser->GetAllUserList();
+ json2($result);
+ }
+
+ /**
+ * 获取带有分页的SVN用户
+ *
+ * 只包含用户名和启用状态
+ */
+ public function GetUserList()
+ {
+ $result = $this->ServiceSvnuser->GetUserList();
+ json2($result);
+ }
+
+ /**
+ * 启用SVN用户
+ */
+ public function EnableUser()
+ {
+ $result = $this->ServiceSvnuser->EnableUser();
+ json2($result);
+ }
+
+ /**
+ * 禁用SVN用户
+ */
+ public function DisableUser()
+ {
+ $result = $this->ServiceSvnuser->DisableUser();
+ json2($result);
+ }
+
+ /**
+ * 修改SVN用户的备注信息
+ */
+ public function EditUserNote()
+ {
+ $result = $this->ServiceSvnuser->EditUserNote();
+ json2($result);
+ }
+
+ /**
+ * 新建SVN用户
+ */
+ public function CreateUser()
+ {
+ $result = $this->ServiceSvnuser->CreateUser();
+ json2($result);
+ }
+
+ /**
+ * 修改SVN用户的密码
+ */
+ public function EditUserPass()
+ {
+ $result = $this->ServiceSvnuser->EditUserPass();
+ json2($result);
+ }
+
+ /**
+ * 删除SVN用户
+ */
+ public function DelUser()
+ {
+ $result = $this->ServiceSvnuser->DelUser();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/Update.php b/02.php/app/controller/Update.php
new file mode 100644
index 0000000..a8c25ac
--- /dev/null
+++ b/02.php/app/controller/Update.php
@@ -0,0 +1,56 @@
+ServiceUpdate = new ServiceUpdate();
+ }
+
+ /**
+ * 获取当前版本信息
+ */
+ public function GetVersion()
+ {
+ $result = $this->ServiceUpdate->GetVersion();
+ json2($result);
+ }
+
+ /**
+ * 检测新版本
+ */
+ public function CheckUpdate()
+ {
+ $result = $this->ServiceUpdate->CheckUpdate();
+ json2($result);
+ }
+
+ /**
+ * 确认更新
+ */
+ public function StartUpdate()
+ {
+ $result = $this->ServiceUpdate->StartUpdate();
+ json2($result);
+ }
+}
diff --git a/02.php/app/controller/base/Base.php b/02.php/app/controller/base/Base.php
new file mode 100644
index 0000000..a06f205
--- /dev/null
+++ b/02.php/app/controller/base/Base.php
@@ -0,0 +1,88 @@
+= $config_daemon['SOCKET_READ_LENGTH']) {
+ json1(200, 0, '数据长度超过' . $config_daemon['SOCKET_READ_LENGTH'] . ' 请向上调整参数:SOCKET_READ_LENGTH');
+ }
+ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("error:" . socket_strerror(socket_last_error()));
+ $server = socket_connect($socket, $config_daemon['IPC_ADDRESS'], (int)$config_daemon['IPC_PORT']);
+ socket_write($socket, $shell);
+ $reply = socket_read($socket, (int)$config_daemon['SOCKET_READ_LENGTH']);
+ socket_close($socket);
+ return unserialize($reply);
+}
+
+/**
+ * 守护进程状态探测
+ * 0 超时
+ * 1 打开
+ * 2 关闭
+ */
+function FunDetectState()
+{
+ $config_daemon = Config::get('daemon');
+
+ $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+
+ @socket_connect($sock, $config_daemon['IPC_ADDRESS'], (int)$config_daemon['IPC_PORT']);
+
+ socket_set_nonblock($sock);
+
+ socket_set_block($sock);
+
+ $v = array($sock);
+
+ $state = @socket_select($r = $v, $w = $v, $f = $v, 5);
+
+ socket_close($sock);
+
+ return $state;
+}
diff --git a/02.php/webman/app/function/json.function.php b/02.php/app/function/json.php
similarity index 100%
rename from 02.php/webman/app/function/json.function.php
rename to 02.php/app/function/json.php
diff --git a/02.php/app/function/message.php b/02.php/app/function/message.php
new file mode 100644
index 0000000..61e55f6
--- /dev/null
+++ b/02.php/app/function/message.php
@@ -0,0 +1,42 @@
+ $code,
+ 'status' => $status,
+ 'message' => $message,
+ 'data' => $data
+ ];
+}
+
+function json1($code = 200, $status = 1, $message = '成功', $data = [])
+{
+ header('Content-Type:application/json; charset=utf-8');
+ // http_response_code($code);
+ exit(json_encode([
+ 'code' => $code,
+ 'status' => $status,
+ 'message' => $message,
+ 'data' => $data
+ ]));
+}
+
+function json2($message = ['code' => 200, 'status' => 1, 'message' => '成功', 'data' => []])
+{
+ header('Content-Type:application/json; charset=utf-8');
+ // http_response_code($code);
+ exit(json_encode([
+ 'code' => $message['code'],
+ 'status' => $message['status'],
+ 'message' => $message['message'],
+ 'data' => $message['data']
+ ]));
+}
diff --git a/02.php/webman/app/function/string.function.php b/02.php/app/function/string.php
similarity index 100%
rename from 02.php/webman/app/function/string.function.php
rename to 02.php/app/function/string.php
diff --git a/02.php/webman/app/function/update.function.php b/02.php/app/function/update.php
similarity index 100%
rename from 02.php/webman/app/function/update.function.php
rename to 02.php/app/function/update.php
diff --git a/02.php/webman/app/controller/Unimportant.php b/02.php/app/service/Common.php
similarity index 86%
rename from 02.php/webman/app/controller/Unimportant.php
rename to 02.php/app/service/Common.php
index c05a3f1..b9540ea 100644
--- a/02.php/webman/app/controller/Unimportant.php
+++ b/02.php/app/service/Common.php
@@ -3,24 +3,36 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 19:25:42
+ * @LastEditTime: 2022-05-07 12:11:45
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use ServiceVerifycode;
-use support\Request;
+use Verifycode;
-/**
- * 登录注销等公共类
- */
-class Unimportant extends Core
+class Common extends Base
{
+ /**
+ * 其它服务层对象
+ *
+ * @var object
+ */
+ private $Svnuser;
+ private $Logs;
+
+ function __construct()
+ {
+ parent::__construct();
+
+ $this->Svnuser = new Svnuser();
+ $this->Logs = new Logs();
+ }
+
/**
* 登录
*/
- public function Login(Request $request)
+ public function Login()
{
$codeResult = $this->database->get('verification_code', [
'end_time'
@@ -59,7 +71,7 @@ class Unimportant extends Core
}
} else if ($this->payload['user_role'] == 2) {
//进行用户数据同步
- $syncResult = parent::SyncUserToDb();
+ $syncResult = $this->Svnuser->SyncUserToDb();
if ($syncResult['status'] != 1) {
return message($syncResult['code'], $syncResult['status'], $syncResult['message'], $syncResult['data']);
}
@@ -81,11 +93,11 @@ class Unimportant extends Core
}
}
- parent::InsertLog(
+ $this->Logs->InsertLog(
'用户登录',
'登陆成功 '
. '账号:' . $this->payload['user_name'] . ' '
- . 'IP地址:' . $request->getRealIp(true),
+ . 'IP地址:' . $_SERVER["REMOTE_ADDR"],
$this->payload['user_name']
);
@@ -104,7 +116,7 @@ class Unimportant extends Core
* 每次注销触发主动扫描黑名单 将名单中过期的token删除
* 目的:实现用户注销后尚未过期的token无法继续使用
*/
- public function Logout(Request $request)
+ public function Logout()
{
//清理过期token
$this->CleanBlack();
@@ -112,9 +124,9 @@ class Unimportant extends Core
//加入本token
$this->AddBlack();
- parent::InsertLog(
+ $this->Logs->InsertLog(
'用户注销',
- '账号:' . $this->userName . 'IP地址:' . $request->getRealIp(true),
+ '账号:' . $this->userName . 'IP地址:' . $_SERVER["REMOTE_ADDR"],
$this->userName
);
@@ -135,7 +147,7 @@ class Unimportant extends Core
/**
* 获取验证码
*/
- public function GetVeryfyCode(Request $request)
+ public function GetVeryfyCode()
{
//清除过期验证码
$this->Clean();
@@ -164,7 +176,7 @@ class Unimportant extends Core
'insert_time' => date('Y-m-d H:i:s')
]);
- $varification = new ServiceVerifycode(134, 32, $code);
+ $varification = new Verifycode(134, 32, $code);
$imageString = $varification->CreateVerifacationImage();
diff --git a/02.php/webman/app/controller/Logs.php b/02.php/app/service/Logs.php
similarity index 73%
rename from 02.php/webman/app/controller/Logs.php
rename to 02.php/app/service/Logs.php
index b4838c5..0b487dd 100644
--- a/02.php/webman/app/controller/Logs.php
+++ b/02.php/app/service/Logs.php
@@ -3,20 +3,23 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 14:35:35
+ * @LastEditTime: 2022-05-06 21:37:57
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use support\Request;
-
-class Logs extends Core
+class Logs extends Base
{
+ function __construct()
+ {
+ parent::__construct();
+ }
+
/**
* 获取日志列表
*/
- public function GetLogList(Request $request)
+ public function GetLogList()
{
$pageSize = $this->payload['pageSize'];
$currentPage = $this->payload['currentPage'];
@@ -65,7 +68,7 @@ class Logs extends Core
/**
* 清空日志
*/
- public function ClearLogs(Request $request)
+ public function ClearLogs()
{
$this->database->delete('logs', [
'log_id[>]' => 0
@@ -73,4 +76,17 @@ class Logs extends Core
return message();
}
+
+ /**
+ * 写入日志
+ */
+ public function InsertLog($log_type_name = '', $log_content = '', $log_add_user_name = '')
+ {
+ $this->database->insert('logs', [
+ 'log_type_name' => $log_type_name,
+ 'log_content' => $log_content,
+ 'log_add_user_name' => $log_add_user_name,
+ 'log_add_time' => date('Y-m-d H:i:s')
+ ]);
+ }
}
diff --git a/02.php/webman/app/controller/Mail.php b/02.php/app/service/Mail.php
similarity index 94%
rename from 02.php/webman/app/controller/Mail.php
rename to 02.php/app/service/Mail.php
index 32394dc..26cd737 100644
--- a/02.php/webman/app/controller/Mail.php
+++ b/02.php/app/service/Mail.php
@@ -3,20 +3,28 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 18:54:21
+ * @LastEditTime: 2022-05-06 22:53:10
* @Description: QQ:1801168257
*/
-namespace app\controller;
-
-use support\Request;
+namespace app\service;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
-class Mail extends Core
+class Mail extends Base
{
+ private $mail;
+
+ function __construct()
+ {
+ parent::__construct();
+
+ $this->mail = new PHPMailer(true);
+ $this->mail->setLanguage('zh_cn', BASE_PATH . '/extension/PHPMailer-6.6.0/language/'); //加载错误消息翻译包
+ }
+
/**
* 发送邮件的模板函数
*
@@ -128,7 +136,7 @@ class Mail extends Core
/**
* 获取邮件配置信息
*/
- public function GetEmail(Request $request)
+ public function GetEmail()
{
$mail_smtp = $this->database->get('options', [
'option_value'
@@ -188,7 +196,7 @@ class Mail extends Core
/**
* 修改邮件配置信息
*/
- public function EditEmail(Request $request)
+ public function EditEmail()
{
$this->database->update('options', [
'option_value' => serialize([
@@ -211,7 +219,7 @@ class Mail extends Core
/**
* 发送测试邮件
*/
- public function SendTest(Request $request)
+ public function SendTest()
{
$host = $this->payload['host'];
$auth = $this->payload['auth'];
diff --git a/02.php/webman/app/controller/Personal.php b/02.php/app/service/Personal.php
similarity index 88%
rename from 02.php/webman/app/controller/Personal.php
rename to 02.php/app/service/Personal.php
index db9cd77..06760a4 100644
--- a/02.php/webman/app/controller/Personal.php
+++ b/02.php/app/service/Personal.php
@@ -3,20 +3,23 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 19:47:46
+ * @LastEditTime: 2022-05-06 21:38:02
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use support\Request;
-
-class Personal extends Core
+class Personal extends Base
{
+ function __construct()
+ {
+ parent::__construct();
+ }
+
/**
* 管理人员修改自己的账号
*/
- public function EditAdminUserName(Request $request)
+ public function EditAdminUserName()
{
if ($this->payload['userName'] != $this->payload['confirm']) {
return message(200, 0, '输入不一致');
@@ -47,7 +50,7 @@ class Personal extends Core
/**
* 管理人员修改自己的密码
*/
- public function EditAdminUserPass(Request $request)
+ public function EditAdminUserPass()
{
if ($this->payload['password'] != $this->payload['confirm']) {
return message(200, 0, '输入不一致');
@@ -69,7 +72,7 @@ class Personal extends Core
/**
* SVN用户修改自己的密码
*/
- public function EditSvnUserPass(Request $request)
+ public function EditSvnUserPass()
{
if ($this->payload['newPassword'] != $this->payload['confirm']) {
return message(200, 0, '输入不一致');
@@ -101,7 +104,7 @@ class Personal extends Core
return message(200, 0, '用户不存在');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_passwd_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
$this->database->update('svn_users', [
'svn_user_pass' => $this->payload['newPassword']
diff --git a/02.php/app/service/Safe.php b/02.php/app/service/Safe.php
new file mode 100644
index 0000000..0b7304b
--- /dev/null
+++ b/02.php/app/service/Safe.php
@@ -0,0 +1,19 @@
+config_svnadmin_svn['rep_base_path']));
+ $repSize = FunFormatSize(FunGetDirSizeDu($this->config_svn['rep_base_path']));
//备份占用体积
- $backupSize = FunFormatSize(FunGetDirSizeDu($this->config_svnadmin_svn['backup_base_path']));
+ $backupSize = FunFormatSize(FunGetDirSizeDu($this->config_svn['backup_base_path']));
//SVN仓库数量
$repCount = count($this->SVNAdminRep->GetSimpleRepList());
diff --git a/02.php/webman/app/controller/Svn.php b/02.php/app/service/Svn.php
similarity index 53%
rename from 02.php/webman/app/controller/Svn.php
rename to 02.php/app/service/Svn.php
index 4b53fe1..1bf7384 100644
--- a/02.php/webman/app/controller/Svn.php
+++ b/02.php/app/service/Svn.php
@@ -3,22 +3,25 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 17:17:23
+ * @LastEditTime: 2022-05-06 21:38:12
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use support\Request;
+class Svn extends Base
+{
+ function __construct()
+ {
+ parent::__construct();
+ }
-class Svn extends Core
-{
/**
* 获取Subversion运行状态 用于页头提醒
*/
- public function GetStatus(Request $request)
+ public function GetStatus()
{
- $result = shellPassthru("ps auxf | grep -v 'grep' | grep svnserve");
+ $result = FunShellExec("ps auxf | grep -v 'grep' | grep svnserve");
$result = $result['result'];
if ($result == '') {
@@ -34,9 +37,9 @@ class Svn extends Core
* 先从Subversion配置文件获取绑定端口和主机
* 然后与listen.json配置文件中的端口和主机进行对比和同步
*/
- public function GetCheckout(Request $request)
+ public function GetCheckout()
{
- $result = parent::GetSvnserveListen();
+ $result = $this->GetSvnserveListen();
$checkoutHost = $result[$result['enable']];
if ($result['bindPort'] != 3690) {
$checkoutHost .= ':' . $result['bindPort'];
@@ -50,13 +53,13 @@ class Svn extends Core
/**
* 获取Subversion的详细信息
*/
- public function GetDetail(Request $request)
+ public function GetDetail()
{
//获取绑定主机、端口等信息
- $bindInfo = parent::GetSvnserveListen();
+ $bindInfo = $this->GetSvnserveListen();
//检测运行信息
- $runInfo = shellPassthru('ps auxf|grep -v "grep"|grep svnserve');
+ $runInfo = FunShellExec('ps auxf|grep -v "grep"|grep svnserve');
$runInfo = $runInfo['result'];
//检测安装信息
@@ -79,9 +82,9 @@ class Svn extends Core
//检测subversion版本
$version = '-';
if ($installed != 0) {
- $versionInfo = shellPassthru('svnserve --version');
+ $versionInfo = FunShellExec('svnserve --version');
$versionInfo = $versionInfo['result'];
- preg_match_all($this->config_svnadmin_reg['REG_SUBVERSION_VERSION'], $versionInfo, $versionInfoPreg);
+ preg_match_all($this->config_reg['REG_SUBVERSION_VERSION'], $versionInfo, $versionInfoPreg);
if (array_key_exists(0, $versionInfoPreg[0])) {
$version = trim($versionInfoPreg[1][0]);
} else {
@@ -96,67 +99,138 @@ class Svn extends Core
'bindHost' => $bindInfo['bindHost'],
'manageHost' => $bindInfo['manageHost'],
'enable' => $bindInfo['enable'],
- 'svnserveLog' => $this->config_svnadmin_svn['svnserve_log_file']
+ 'svnserveLog' => $this->config_svn['svnserve_log_file']
]);
}
+ /**
+ * 获取svnserve端口和主机情况
+ *
+ * 先从svnserve配置文件获取绑定端口和主机
+ * 然后向数据库同步
+ *
+ * 绑定端口
+ * 绑定地址
+ * 管理地址
+ * 检出地址的启用地址
+ */
+ public function GetSvnserveListen()
+ {
+ $bindPort = '';
+ $bindHost = '';
+
+ $svnserveContent = FunShellExec(sprintf("cat '%s'", $this->config_svn['svnserve_env_file']));
+ $svnserveContent = $svnserveContent['result'];
+
+ //匹配端口
+ if (preg_match('/--listen-port[\s]+([0-9]+)/', $svnserveContent, $portMatchs) != 0) {
+ $bindPort = trim($portMatchs[1]);
+ }
+
+ //匹配地址
+ if (preg_match('/--listen-host[\s]+([\S]+)\b/', $svnserveContent, $hostMatchs) != 0) {
+ $bindHost = trim($hostMatchs[1]);
+ }
+
+ $svnserve_listen = $this->database->get('options', [
+ 'option_value'
+ ], [
+ 'option_name' => 'svnserve_listen'
+ ]);
+
+ $insert = [
+ "bindPort" => $bindPort == '' ? 3690 : $bindPort,
+ "bindHost" => $bindHost == '' ? '0.0.0.0' : $bindHost,
+ "manageHost" => "127.0.0.1",
+ "enable" => "manageHost"
+ ];
+
+ if ($svnserve_listen == null) {
+ //插入
+ $this->database->insert('options', [
+ 'option_name' => 'svnserve_listen',
+ 'option_value' => serialize($insert),
+ 'option_description' => ''
+ ]);
+ } else if ($svnserve_listen['option_value'] == '') {
+ //更新
+ $this->database->update('options', [
+ 'option_value' => serialize($insert),
+ ], [
+ 'option_name' => 'svnserve_listen',
+ ]);
+ } else {
+ //更新
+ $svnserve_listen = unserialize($svnserve_listen['option_value']);
+ $insert['manageHost'] = $svnserve_listen['manageHost'] == '' ? '127.0.0.1' : $svnserve_listen['manageHost'];
+ $insert['enable'] = $svnserve_listen['enable'] == '' ? 'manageHost' : $svnserve_listen['enable'];
+ $this->database->update('options', [
+ 'option_value' => serialize($insert),
+ ], [
+ 'option_name' => 'svnserve_listen',
+ ]);
+ }
+
+ return $insert;
+ }
+
/**
* 安装SVN
*/
- public function Install(Request $request)
+ public function Install()
{
}
/**
* 卸载SVN
*/
- public function UnInstall(Request $request)
+ public function UnInstall()
{
}
/**
* 启动SVN
*/
- public function Start(Request $request)
+ public function Start()
{
- passthru("systemctl start svnserve");
+ FunShellExec("systemctl start svnserve");
return message();
}
/**
* 停止SVN
*/
- public function Stop(Request $request)
+ public function Stop()
{
- passthru("systemctl stop svnserve");
+ FunShellExec("systemctl stop svnserve");
return message();
}
/**
* 修改svnserve的绑定端口
*/
- public function EditPort(Request $request)
+ public function EditPort()
{
//port不能为空
//获取现在的端口与要修改的端口对比检查是否相同
- $result = parent::GetSvnserveListen();
+ $result = $this->GetSvnserveListen();
if ($this->payload['bindPort'] == $result['bindPort']) {
return message(200, 0, '无需更换,端口相同');
}
//停止svnserve
- passthru('systemctl stop svnserve');
+ FunShellExec('systemctl stop svnserve');
//重新构建配置文件内容
- $config = sprintf("OPTIONS=\"-r '%s' --config-file '%s' --log-file '%s' --listen-port %s --listen-host %s\"", $this->config_svnadmin_svn['rep_base_path'], $this->config_svnadmin_svn['svn_conf_file'], $this->config_svnadmin_svn['svnserve_log_file'], $this->payload['bindPort'], $result['bindHost']);
+ $config = sprintf("OPTIONS=\"-r '%s' --config-file '%s' --log-file '%s' --listen-port %s --listen-host %s\"", $this->config_svn['rep_base_path'], $this->config_svn['svn_conf_file'], $this->config_svn['svnserve_log_file'], $this->payload['bindPort'], $result['bindHost']);
//写入配置文件
- passthru('echo \'' . $config . '\' > ' . $this->config_svnadmin_svn['svnserve_env_file']);
+ FunShellExec('echo \'' . $config . '\' > ' . $this->config_svn['svnserve_env_file']);
//启动svnserve
- $result = shellPassthru('systemctl start svnserve');
+ $result = FunShellExec('systemctl start svnserve');
if ($result['resultCode'] != 0) {
return message(200, 0, '启动异常' . $result['error']);
@@ -168,29 +242,29 @@ class Svn extends Core
/**
* 修改svnserve的绑定主机
*/
- public function EditHost(Request $request)
+ public function EditHost()
{
//host不能为空
//不能带前缀如http或者https
//获取现在的绑定主机与要修改的主机对比检查是否相同
- $result = parent::GetSvnserveListen();
+ $result = $this->GetSvnserveListen();
if ($this->payload['bindHost'] == $result['bindHost']) {
return message(200, 0, '无需更换,地址相同');
}
//停止svnserve
- passthru('systemctl stop svnserve');
+ FunShellExec('systemctl stop svnserve');
//重新构建配置文件内容
- $config = sprintf("OPTIONS=\"-r '%s' --config-file '%s' --log-file '%s' --listen-port %s --listen-host %s\"", $this->config_svnadmin_svn['rep_base_path'], $this->config_svnadmin_svn['svn_conf_file'], $this->config_svnadmin_svn['svnserve_log_file'], $result['bindPort'], $this->payload['bindHost']);
+ $config = sprintf("OPTIONS=\"-r '%s' --config-file '%s' --log-file '%s' --listen-port %s --listen-host %s\"", $this->config_svn['rep_base_path'], $this->config_svn['svn_conf_file'], $this->config_svn['svnserve_log_file'], $result['bindPort'], $this->payload['bindHost']);
//写入配置文件
- passthru('echo \'' . $config . '\' > ' . $this->config_svnadmin_svn['svnserve_env_file']);
+ FunShellExec('echo \'' . $config . '\' > ' . $this->config_svn['svnserve_env_file']);
//启动svnserve
- $result = shellPassthru('systemctl start svnserve');
+ $result = FunShellExec('systemctl start svnserve');
if ($result['resultCode'] != 0) {
return message(200, 0, '启动异常' . $result['error']);
@@ -202,12 +276,12 @@ class Svn extends Core
/**
* 修改管理系统主机名
*/
- public function EditManageHost(Request $request)
+ public function EditManageHost()
{
//不能为空
//不能带前缀如http或者https
- $result = parent::GetSvnserveListen();
+ $result = $this->GetSvnserveListen();
if ($this->payload['manageHost'] == $result['manageHost']) {
return message(200, 0, '无需更换,地址相同');
@@ -227,9 +301,9 @@ class Svn extends Core
/**
* 修改检出地址
*/
- public function EditEnable(Request $request)
+ public function EditEnable()
{
- $result = parent::GetSvnserveListen();
+ $result = $this->GetSvnserveListen();
//enable的值可为 manageHost、bindHost
@@ -247,32 +321,32 @@ class Svn extends Core
/**
* 获取配置文件列表
*/
- public function GetConfig(Request $request)
+ public function GetConfig()
{
return message(200, 1, '成功', [
[
'key' => '仓库父目录',
- 'value' => $this->config_svnadmin_svn['rep_base_path']
+ 'value' => $this->config_svn['rep_base_path']
],
[
'key' => '仓库配置文件',
- 'value' => $this->config_svnadmin_svn['svn_conf_file']
+ 'value' => $this->config_svn['svn_conf_file']
],
[
'key' => '仓库权限文件',
- 'value' => $this->config_svnadmin_svn['svn_authz_file']
+ 'value' => $this->config_svn['svn_authz_file']
],
[
'key' => '用户账号文件',
- 'value' => $this->config_svnadmin_svn['svn_passwd_file']
+ 'value' => $this->config_svn['svn_passwd_file']
],
[
'key' => '备份目录',
- 'value' => $this->config_svnadmin_svn['backup_base_path']
+ 'value' => $this->config_svn['backup_base_path']
],
[
'key' => 'svnserve环境变量文件',
- 'value' => $this->config_svnadmin_svn['svnserve_env_file']
+ 'value' => $this->config_svn['svnserve_env_file']
],
]);
}
diff --git a/02.php/webman/app/controller/Svngroup.php b/02.php/app/service/Svngroup.php
similarity index 86%
rename from 02.php/webman/app/controller/Svngroup.php
rename to 02.php/app/service/Svngroup.php
index c0fca68..1d944f4 100644
--- a/02.php/webman/app/controller/Svngroup.php
+++ b/02.php/app/service/Svngroup.php
@@ -3,16 +3,19 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-05 14:38:32
+ * @LastEditTime: 2022-05-07 14:19:26
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use support\Request;
-
-class Svngroup extends Core
+class Svngroup extends Base
{
+ function __construct()
+ {
+ parent::__construct();
+ }
+
/**
* 将SVN分组数据同步到数据库
*
@@ -38,8 +41,6 @@ class Svngroup extends Core
$combinArray = array_combine(FunArrayColumn($svnAndGroupList, 'groupName'), FunArrayColumn($svnAndGroupList, 'include'));
- // return message(200,0,'调试',$combinArray);
-
foreach ($dbGroupPassList as $key => $value) {
if (!in_array($value['svn_group_name'], $svnGroupList)) {
$this->database->delete('svn_groups', [
@@ -173,7 +174,7 @@ class Svngroup extends Core
}
//写入配置文件
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//写入数据库
$this->database->insert('svn_groups', [
@@ -201,7 +202,7 @@ class Svngroup extends Core
return message(200, 0, '分组不存在');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//从数据库删除
$this->database->delete('svn_groups', [
@@ -239,7 +240,7 @@ class Svngroup extends Core
return message(200, 0, '文件格式错误(不存在[groups]标识)');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
return message();
}
@@ -324,7 +325,7 @@ class Svngroup extends Core
return message(200, 0, '要添加的用户已存在该分组');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
return message();
}
@@ -345,7 +346,7 @@ class Svngroup extends Core
return message(200, 0, '要删除的用户不在该分组');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
return message();
}
@@ -377,7 +378,7 @@ class Svngroup extends Core
return message(200, 0, '存在分组循环嵌套的情况');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
return message();
}
@@ -398,11 +399,55 @@ class Svngroup extends Core
return message(200, 0, '要删除的分组不在该分组');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
return message();
}
+ /**
+ * 获取用户所在的所有分组
+ *
+ * 包括直接包含关系 如
+ * group1=user1
+ *
+ * 和间接包含关系 如
+ * group1=user1
+ * group2=@group1
+ * group3=@group2
+ * group4=@group3
+ */
+ public function GetSvnUserAllGroupList($userName)
+ {
+ $authzContent = $this->authzContent;
+
+ //所有的分组列表
+ $allGroupList = $this->SVNAdminGroup->GetSvnGroupList($authzContent);
+
+ //用户所在的分组列表
+ $userGroupList = $this->SVNAdminUser->GetSvnUserGroupList($authzContent, $userName);
+
+ //剩余的分组列表
+ $leftGroupList = array_diff($allGroupList, $userGroupList);
+
+ //循环匹配 直到匹配到与该用户相关的有权限的用户组为止
+ loop:
+ $userGroupListBack = $userGroupList;
+ foreach ($userGroupList as $group1) {
+ $newList = $this->SVNAdminGroup->GetSvnGroupGroupList($authzContent, $group1);
+ foreach ($leftGroupList as $key2 => $group2) {
+ if (in_array($group2, $newList)) {
+ array_push($userGroupList, $group2);
+ unset($leftGroupList[$key2]);
+ }
+ }
+ }
+ if ($userGroupList != $userGroupListBack) {
+ goto loop;
+ }
+
+ return $userGroupList;
+ }
+
/**
* 获取分组所在的所有分组
*
diff --git a/02.php/webman/app/controller/Svnrep.php b/02.php/app/service/Svnrep.php
similarity index 87%
rename from 02.php/webman/app/controller/Svnrep.php
rename to 02.php/app/service/Svnrep.php
index 358e6ef..1b96f42 100644
--- a/02.php/webman/app/controller/Svnrep.php
+++ b/02.php/app/service/Svnrep.php
@@ -3,17 +3,31 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-05 15:49:48
+ * @LastEditTime: 2022-05-07 14:21:35
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use ServiceTransfer;
-use support\Request;
+use Transfer;
-class Svnrep extends Core
+class Svnrep extends Base
{
+ /**
+ * 服务层对象
+ *
+ * @var object
+ */
+ private $Svngroup;
+
+ function __construct()
+ {
+ parent::__construct();
+
+ $this->Svngroup = new Svngroup();
+ $this->Svn = new Svn();
+ }
+
/**
* 新建仓库
*/
@@ -43,11 +57,11 @@ class Svnrep extends Core
//创建空仓库
//解决创建中文仓库乱码问题
- passthru('export LC_CTYPE=en_US.UTF-8 && svnadmin create ' . $this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name']);
+ FunShellExec('export LC_CTYPE=en_US.UTF-8 && svnadmin create ' . $this->config_svn['rep_base_path'] . $this->payload['rep_name']);
if ($this->payload['rep_type'] == '2') {
//以指定的目录结构初始化仓库
- $this->SVNAdminRep->InitRepStruct($this->config_svnadmin_svn['templete_init_struct'], $this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name']);
+ $this->SVNAdminRep->InitRepStruct($this->config_svn['templete_init_struct'], $this->config_svn['rep_base_path'] . $this->payload['rep_name']);
}
//检查是否创建成功
@@ -59,7 +73,7 @@ class Svnrep extends Core
//向authz写入仓库信息
$status = $this->SVNAdminRep->SetRepAuthz($this->authzContent, $this->payload['rep_name'], '/');
if ($status != '1') {
- passthru('echo \'' . $status . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $status . '\' > ' . $this->config_svn['svn_authz_file']);
}
//写入数据库
@@ -96,7 +110,7 @@ class Svnrep extends Core
} else {
//更新
$this->database->update('svn_reps', [
- 'rep_size' => FunGetDirSizeDu($this->config_svnadmin_svn['rep_base_path'] . $value['rep_name']),
+ 'rep_size' => FunGetDirSizeDu($this->config_svn['rep_base_path'] . $value['rep_name']),
'rep_rev' => $this->SVNAdminRep->GetRepRev($value['rep_name'])
], [
'rep_name' => $value['rep_name']
@@ -108,7 +122,7 @@ class Svnrep extends Core
if (!in_array($value, FunArrayColumn($dbRepList, 'rep_name'))) {
$this->database->insert('svn_reps', [
'rep_name' => $value,
- 'rep_size' => FunGetDirSizeDu($this->config_svnadmin_svn['rep_base_path'] . $value),
+ 'rep_size' => FunGetDirSizeDu($this->config_svn['rep_base_path'] . $value),
'rep_note' => '',
'rep_rev' => $this->SVNAdminRep->GetRepRev($value),
'rep_uuid' => ''
@@ -150,7 +164,7 @@ class Svnrep extends Core
}
if ($authzContet != $this->authzContent) {
- passthru('echo \'' . $authzContet . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $authzContet . '\' > ' . $this->config_svn['svn_authz_file']);
}
}
@@ -172,7 +186,7 @@ class Svnrep extends Core
$userRepList = array_merge($userRepList, $this->SVNAdminUser->GetUserPriRepListWithPriAndPath($this->authzContent, $this->userName));
//获取用户所在的所有分组
- $userGroupList = parent::GetSvnUserAllGroupList($this->userName);
+ $userGroupList = $this->Svngroup->GetSvnUserAllGroupList($this->userName);
//获取分组有权限的仓库路径列表
foreach ($userGroupList as $value) {
@@ -195,8 +209,8 @@ class Svnrep extends Core
$authzContent = $this->authzContent;
foreach ($userRepList as $key => $value) {
- $cmd = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", $this->config_svnadmin_svn['rep_base_path'] . $value['repName'], $value['priPath']);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", $this->config_svn['rep_base_path'] . $value['repName'], $value['priPath']);
+ $result = FunShellExec($cmd);
if (strstr($result['error'], 'svnlook: E160013:')) {
//路径在仓库不存在
@@ -210,7 +224,7 @@ class Svnrep extends Core
//写入配置文件
if ($authzContent != $this->authzContent) {
- passthru('echo \'' . $authzContent . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $authzContent . '\' > ' . $this->config_svn['svn_authz_file']);
}
}
@@ -229,7 +243,7 @@ class Svnrep extends Core
$userRepList = array_merge($userRepList, $this->SVNAdminUser->GetUserPriRepListWithPriAndPath($this->authzContent, $this->userName));
//获取用户所在的所有分组
- $userGroupList = parent::GetSvnUserAllGroupList($this->userName);
+ $userGroupList = $this->Svngroup->GetSvnUserAllGroupList($this->userName);
//获取分组有权限的仓库路径列表
foreach ($userGroupList as $value) {
@@ -275,7 +289,7 @@ class Svnrep extends Core
/**
* 获取仓库列表
*/
- public function GetRepList(Request $request)
+ public function GetRepList()
{
/**
* 物理仓库 => authz文件
@@ -449,7 +463,7 @@ class Svnrep extends Core
*
* 目的为使用当前SVN用户的身份来进行被授权过的路径的内容浏览
*/
- $bindInfo = parent::GetSvnserveListen();
+ $bindInfo = $this->Svn->GetSvnserveListen();
$checkoutHost = 'svn://' . $bindInfo['bindHost'];
if ($bindInfo['bindPort'] != '3690') {
$checkoutHost = 'svn://' . $bindInfo['bindHost'] . ':' . $bindInfo['bindPort'];
@@ -644,8 +658,8 @@ class Svnrep extends Core
$path = $this->payload['path'];
//获取全路径的一层目录树
- $cmdSvnlookTree = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", $this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name'], $path);
- $result = shellPassthru($cmdSvnlookTree);
+ $cmdSvnlookTree = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", $this->config_svn['rep_base_path'] . $this->payload['rep_name'], $path);
+ $result = FunShellExec($cmdSvnlookTree);
$result = $result['result'];
$resultArray = explode("\n", trim($result));
unset($resultArray[0]);
@@ -741,8 +755,8 @@ class Svnrep extends Core
$path = $this->payload['path'];
//获取全路径的一层目录树
- $cmdSvnlookTree = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", $this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name'], $path);
- $result = shellPassthru($cmdSvnlookTree);
+ $cmdSvnlookTree = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", $this->config_svn['rep_base_path'] . $this->payload['rep_name'], $path);
+ $result = FunShellExec($cmdSvnlookTree);
$result = $result['result'];
$resultArray = explode("\n", trim($result));
unset($resultArray[0]);
@@ -889,7 +903,7 @@ class Svnrep extends Core
}
//写入
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//返回
return message();
@@ -912,7 +926,7 @@ class Svnrep extends Core
return message(200, 0, '已被删除');
} else {
//写入
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//返回
return message();
@@ -941,7 +955,7 @@ class Svnrep extends Core
}
//写入
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//返回
return message();
@@ -994,7 +1008,7 @@ class Svnrep extends Core
}
//写入
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//返回
return message();
@@ -1017,7 +1031,7 @@ class Svnrep extends Core
return message(200, 0, '已被删除');
} else {
//写入
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//返回
return message();
@@ -1048,7 +1062,7 @@ class Svnrep extends Core
}
//写入
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
//返回
return message();
@@ -1078,7 +1092,7 @@ class Svnrep extends Core
}
//从仓库目录修改仓库名称
- passthru('mv ' . $this->config_svnadmin_svn['rep_base_path'] . $this->payload['old_rep_name'] . ' ' . $this->config_svnadmin_svn['rep_base_path'] . $this->payload['new_rep_name']);
+ FunShellExec('mv ' . $this->config_svn['rep_base_path'] . $this->payload['old_rep_name'] . ' ' . $this->config_svn['rep_base_path'] . $this->payload['new_rep_name']);
//检查修改过的仓库名称是否存在
$checkResult = $this->SVNAdminRep->CheckRepCreate($this->payload['new_rep_name'], '修改仓库名称失败');
@@ -1107,7 +1121,7 @@ class Svnrep extends Core
//从配置文件删除指定仓库的所有路径
$result = $this->SVNAdminRep->DelRepAuthz($this->authzContent, $this->payload['rep_name']);
if ($result != '1') {
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
}
//从数据库中删除
@@ -1116,7 +1130,7 @@ class Svnrep extends Core
]);
//从仓库目录删除仓库文件夹
- passthru('cd ' . $this->config_svnadmin_svn['rep_base_path'] . ' && rm -rf ./' . $this->payload['rep_name']);
+ FunShellExec('cd ' . $this->config_svn['rep_base_path'] . ' && rm -rf ./' . $this->payload['rep_name']);
$checkResult = $this->SVNAdminRep->CheckRepDelete($this->payload['rep_name']);
if ($checkResult['status'] != 1) {
return message($checkResult['code'], $checkResult['status'], $checkResult['message'], $checkResult['data']);
@@ -1154,7 +1168,7 @@ class Svnrep extends Core
*/
public function GetBackupList()
{
- $result = FunGetDirFileList($this->config_svnadmin_svn['backup_base_path']);
+ $result = FunGetDirFileList($this->config_svn['backup_base_path']);
return message(200, 1, '成功', $result);
}
@@ -1182,21 +1196,17 @@ class Svnrep extends Core
/**
* 下载备份文件
*/
- public function DownloadRepBackup(Request $request)
+ public function DownloadRepBackup()
{
- $filePath = $this->config_svnadmin_svn['backup_base_path'] . $this->payload['fileName'];
- return response()->download($filePath);
+ $filePath = $this->config_svn['backup_base_path'] . $this->payload['fileName'];
+ $this->DownloadRepBackup1($filePath, $this->payload['fileName']);
}
/**
* 下载备份文件
*/
- private function DownloadRepBackup1()
+ private function DownloadRepBackup1($filePath, $fileName)
{
- $filePath = $this->config_svnadmin_svn['backup_base_path'] . $this->payload['fileName'];
-
- $fileName = $this->payload['fileName'];
-
//以只读和二进制模式打开文件
$fp = @fopen($filePath, 'rb');
if ($fp) {
@@ -1252,10 +1262,8 @@ class Svnrep extends Core
/**
* 下载备份文件
*/
- private function DownloadRepBackup2()
+ private function DownloadRepBackup2($filePath, $fileName)
{
- $filePath = $this->config_svnadmin_svn['backup_base_path'] . $this->payload['fileName'];
-
//文件类型
$mimeType = 'application/octet-stream';
@@ -1264,72 +1272,35 @@ class Svnrep extends Core
set_time_limit(0);
- $transfer = new ServiceTransfer($filePath, $mimeType, $range);
+ $transfer = new Transfer($filePath, $mimeType, $range);
$transfer->send();
}
/**
- * 下载大文件
+ * 上传文件到备份文件夹
*/
- function send_file($connection, $file_name)
+ public function UploadBackup()
{
- if (!is_file($file_name)) {
- $connection->send("HTTP/1.0 404 File Not Found\r\nContent-Length: 18\r\n\r\n404 File Not Found", true);
- return;
- }
+ if (array_key_exists('file', $_FILES)) {
+ //扩展名
+ $fileType = substr(strrchr($_FILES['file']['name'], '.'), 1);
- // ======发送http头======
- $file_size = filesize($file_name);
- $header = "HTTP/1.1 200 OK\r\n";
- // 这里写的Content-Type是pdf,如果不是pdf文件请修改Content-Type的值
- // mime对应关系参见 https://github.com/walkor/Workerman/blob/master/Protocols/Http/mime.types#L30
- $header .= "Content-Type: application/pdf\r\n";
- $header .= "Connection: keep-alive\r\n";
- $header .= "Content-Length: $file_size\r\n\r\n";
- $connection->send($header, true);
-
- // ======分段发送文件内容=======
- $connection->fileHandler = fopen($file_name, 'r');
- $do_write = function () use ($connection) {
- // 对应客户端的连接发送缓冲区未满时
- while (empty($connection->bufferFull)) {
- // 从磁盘读取文件
- $buffer = fread($connection->fileHandler, 8192);
- // 读不到数据说明文件读到末尾了
- if ($buffer === '' || $buffer === false) {
- return;
- }
- $connection->send($buffer, true);
- }
- };
- // 发生连接发送缓冲区满事件时设置一个标记bufferFull
- $connection->onBufferFull = function ($connection) {
- // 赋值一个bufferFull临时变量给链接对象,标记发送缓冲区满,暂停do_write发送
- $connection->bufferFull = true;
- };
- // 当发送缓冲区数据发送完毕时触发
- $connection->onBufferDrain = function ($connection) use ($do_write) {
- $connection->bufferFull = false;
- $do_write();
- };
- // 执行发送
- $do_write();
- }
+ //文件名
+ $fileName = $_FILES['file']['name'];
+
+ //备份文件夹
+ $localFilePath = $this->config_svn['backup_base_path'] . $fileName;
+
+ //保存
+ $cmd = sprintf("mv '%s' '%s'", $_FILES['file']['tmp_name'], $localFilePath);
+ FunShellExec($cmd);
+ // move_uploaded_file($_FILES['file']['tmp_name'], $localFilePath);
- /**
- * 上传文件到备份文件夹
- */
- public function UploadBackup(Request $request)
- {
- $file = $request->file('file');
- if ($file && $file->isValid()) {
- $localFilePath = $this->config_svnadmin_svn['backup_base_path'] . $file->getUploadName();
- $file->move($localFilePath);
return message();
+ } else {
+ return message(200, 0, '参数不完整');
}
-
- return message(200, 0, '上传失败');
}
/**
@@ -1338,7 +1309,7 @@ class Svnrep extends Core
public function ImportRep()
{
//检查备份文件是否存在
- if (!file_exists($this->config_svnadmin_svn['backup_base_path'] . $this->payload['fileName'])) {
+ if (!file_exists($this->config_svn['backup_base_path'] . $this->payload['fileName'])) {
return message(200, 0, '备份文件不存在');
}
@@ -1370,7 +1341,7 @@ class Svnrep extends Core
}
clearstatcache();
- if (!is_dir($this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name'] . '/' . 'hooks')) {
+ if (!is_dir($this->config_svn['rep_base_path'] . $this->payload['rep_name'] . '/' . 'hooks')) {
return message(200, 0, '仓库不存在或文件损坏');
}
@@ -1434,12 +1405,12 @@ class Svnrep extends Core
'post-revprop-change'
];
- $file_arr = scandir($this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name'] . '/' . 'hooks');
+ $file_arr = scandir($this->config_svn['rep_base_path'] . $this->payload['rep_name'] . '/' . 'hooks');
foreach ($file_arr as $file_item) {
if ($file_item != '.' && $file_item != '..') {
if (in_array($file_item, $hooks_file_list)) {
- $temp = shellPassthru(sprintf("cat '%s'", $this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name'] . '/' . 'hooks' . '/' . $file_item));
+ $temp = FunShellExec(sprintf("cat '%s'", $this->config_svn['rep_base_path'] . $this->payload['rep_name'] . '/' . 'hooks' . '/' . $file_item));
$hooks_type_list[$file_item]['shell'] = $temp['result'];
$hooks_type_list[$file_item]['shell'] = trim($hooks_type_list[$file_item]['shell']);
}
@@ -1454,9 +1425,9 @@ class Svnrep extends Core
*/
public function EditRepHook()
{
- $cmd = sprintf("echo '%s' > '%s'", trim($this->payload['content']), $this->config_svnadmin_svn['rep_base_path'] . $this->payload['rep_name'] . '/hooks/' . $this->payload['type']);
+ $cmd = sprintf("echo '%s' > '%s'", trim($this->payload['content']), $this->config_svn['rep_base_path'] . $this->payload['rep_name'] . '/hooks/' . $this->payload['type']);
- passthru($cmd);
+ FunShellExec($cmd);
return message();
}
diff --git a/02.php/webman/app/controller/Svnuser.php b/02.php/app/service/Svnuser.php
similarity index 70%
rename from 02.php/webman/app/controller/Svnuser.php
rename to 02.php/app/service/Svnuser.php
index 93df521..9ce7eab 100644
--- a/02.php/webman/app/controller/Svnuser.php
+++ b/02.php/app/service/Svnuser.php
@@ -3,16 +3,70 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-05 14:37:56
+ * @LastEditTime: 2022-05-07 14:23:38
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use support\Request;
-
-class Svnuser extends Core
+class Svnuser extends Base
{
+ function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * 将SVN用户数据同步到数据库
+ *
+ * 目的为维护用户启用状态和自定义备注信息
+ */
+ public function SyncUserToDb()
+ {
+ $svnUserPassList = $this->SVNAdminUser->GetSvnUserPassList($this->passwdContent);
+ if ($svnUserPassList == 0) {
+ return message(200, 0, '文件格式错误(不存在[users]标识)');
+ }
+ $dbUserPassList = $this->database->select('svn_users', [
+ 'svn_user_id',
+ 'svn_user_name',
+ 'svn_user_pass',
+ 'svn_user_status',
+ 'svn_user_note'
+ ]);
+
+ $combinArray1 = array_combine(FunArrayColumn($svnUserPassList, 'userName'), FunArrayColumn($svnUserPassList, 'disabled'));
+ $combinArray2 = array_combine(FunArrayColumn($svnUserPassList, 'userName'), FunArrayColumn($svnUserPassList, 'userPass'));
+ foreach ($dbUserPassList as $value) {
+ if (!in_array($value['svn_user_name'], FunArrayColumn($svnUserPassList, 'userName'))) {
+ $this->database->delete('svn_users', [
+ 'svn_user_name' => $value['svn_user_name']
+ ]);
+ } else {
+ //更新启用状态和密码
+ $this->database->update('svn_users', [
+ 'svn_user_pass' => $combinArray2[$value['svn_user_name']],
+ 'svn_user_status' => !$combinArray1[$value['svn_user_name']]
+ ], [
+ 'svn_user_name' => $value['svn_user_name']
+ ]);
+ }
+ }
+
+ foreach ($svnUserPassList as $value) {
+ if (!in_array($value['userName'], FunArrayColumn($dbUserPassList, 'svn_user_name'))) {
+ $this->database->insert('svn_users', [
+ 'svn_user_name' => $value['userName'],
+ 'svn_user_pass' => $value['userPass'],
+ 'svn_user_status' => !$value['disabled'],
+ 'svn_user_note' => ''
+ ]);
+ }
+ }
+
+ return message();
+ }
+
/**
* 获取全部的SVN用户
*
@@ -36,7 +90,7 @@ class Svnuser extends Core
public function GetUserList()
{
//将SVN用户数据同步到数据库
- $syncResult = parent::SyncUserToDb();
+ $syncResult = $this->SyncUserToDb();
if ($syncResult['status'] != 1) {
return message($syncResult['code'], $syncResult['status'], $syncResult['message'], $syncResult['data']);
}
@@ -103,7 +157,7 @@ class Svnuser extends Core
return message(200, 0, '要启用的用户不存在');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_passwd_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
return message();
}
@@ -121,7 +175,7 @@ class Svnuser extends Core
return message(200, 0, '要禁用的用户不存在');
}
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_passwd_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
return message();
}
@@ -166,7 +220,7 @@ class Svnuser extends Core
}
//写入配置文件
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_passwd_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
//写入数据库
$this->database->insert('svn_users', [
@@ -199,7 +253,7 @@ class Svnuser extends Core
}
//写入配置文件
- passthru('echo \'' . $result . '\' > ' . $this->config_svnadmin_svn['svn_passwd_file']);
+ FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
//写入数据库
$this->database->update('svn_users', [
@@ -238,9 +292,9 @@ class Svnuser extends Core
'svn_user_name' => $this->payload['svn_user_name']
]);
- passthru('echo \'' . $resultAuthz . '\' > ' . $this->config_svnadmin_svn['svn_authz_file']);
+ FunShellExec('echo \'' . $resultAuthz . '\' > ' . $this->config_svn['svn_authz_file']);
- passthru('echo \'' . $resultPasswd . '\' > ' . $this->config_svnadmin_svn['svn_passwd_file']);
+ FunShellExec('echo \'' . $resultPasswd . '\' > ' . $this->config_svn['svn_passwd_file']);
return message();
}
diff --git a/02.php/webman/app/controller/Update.php b/02.php/app/service/Update.php
similarity index 54%
rename from 02.php/webman/app/controller/Update.php
rename to 02.php/app/service/Update.php
index 4d649b6..641e7c9 100644
--- a/02.php/webman/app/controller/Update.php
+++ b/02.php/app/service/Update.php
@@ -3,23 +3,26 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 17:32:56
+ * @LastEditTime: 2022-05-07 14:25:15
* @Description: QQ:1801168257
*/
-namespace app\controller;
+namespace app\service;
-use support\Request;
+class Update extends Base
+{
+ function __construct()
+ {
+ parent::__construct();
+ }
-class Update extends Core
-{
/**
* 获取当前版本信息
*/
public function GetVersion()
{
return message(200, 1, '成功', [
- 'current_verson' => $this->config_svnadmin_version['version'],
+ 'current_verson' => $this->config_version['version'],
'github' => 'https://github.com/witersen/svnAdminV2.0',
'gitee' => 'https://gitee.com/witersen/SvnAdminV2.0',
'author' => 'https://www.witersen.com'
@@ -31,38 +34,27 @@ class Update extends Core
*/
public function CheckUpdate($payload)
{
- foreach ($this->config_svnadmin_update['update_server'] as $key => $value) {
+ foreach ($this->config_update['update_server'] as $key => $value) {
$versionInfo = FunCurlRequest($value);
if ($versionInfo != null) {
$versionInfo = json_decode($versionInfo, true);
$latestVersion = $versionInfo['latestVersion'];
- if ($latestVersion == $this->config_svnadmin_version['version']) {
- $data['status'] = 1;
- $data['message'] = '当前版本为最新版';
- $data['data'] = null;
- return $data;
- } else if ($latestVersion > $this->config_svnadmin_version['version']) {
- $data['status'] = 1;
- $data['message'] = '有更新';
- $data['data'] = array(
+ if ($latestVersion == $this->config_version['version']) {
+ return message(200, 1, '当前版本为最新版');
+ } else if ($latestVersion > $this->config_version['version']) {
+ return message(200, 1, '有更新', [
'latestVersion' => $versionInfo['latestVersion'],
'fixedContent' => implode('
', $versionInfo['fixedContent']) == '' ? '暂无内容' : implode('
', $versionInfo['fixedContent']),
'newContent' => implode('
', $versionInfo['newContent']) == '' ? '暂无内容' : implode('
', $versionInfo['newContent']),
'updateType' => $versionInfo['updateType'],
'updateStep' => $versionInfo['updateStep']
- );
- return $data;
- } else if ($latestVersion < $this->config_svnadmin_version['version']) {
- $data['status'] = 0;
- $data['message'] = '系统版本错误';
- $data['data'] = null;
- return $data;
+ ]);
+ } else if ($latestVersion < $this->config_version['version']) {
+ return message(200, 0, '系统版本错误');
}
}
}
- $data['status'] = 0;
- $data['message'] = '检测更新超时';
- return $data;
+ return message(200, 0, '检测更新超时');
}
/**
diff --git a/02.php/app/service/base/Base.php b/02.php/app/service/base/Base.php
new file mode 100644
index 0000000..b7e87ab
--- /dev/null
+++ b/02.php/app/service/base/Base.php
@@ -0,0 +1,280 @@
+config_routers = Config::get('router'); //路由
+ $this->config_database = Config::get('database'); //数据库配置
+ $this->config_version = Config::get('version'); //版本
+ $this->config_update = Config::get('update'); //升级检测
+ $this->config_svn = Config::get('svn'); //仓库
+ $this->config_reg = Config::get('reg'); //正则
+ $this->config_sign = Config::get('sign'); //密钥
+
+ //token
+ $this->token = $token;
+
+ /**
+ * 2、检查接口类型
+ */
+ if (!in_array($type, array_keys($this->config_routers['public']))) {
+ json1(401, 0, '无效的接口类型');
+ }
+
+ /**
+ * 3、检查白名单路由
+ */
+ if (!in_array("$controller_perifx/$action", $this->config_routers['public'][$type])) {
+ //如果请求不在对应类型的白名单中 则需要进行token校验
+ $result = $this->CheckToken();
+ if ($result['status'] != 1) {
+ //token校验不通过则返回
+ json1($result['code'], $result['status'], $result['message']);
+ }
+ }
+
+ /**
+ * 4、用户信息获取
+ */
+ $this->GetUserInfo();
+
+ /**
+ * 5、检查特定角色权限路由
+ */
+ if ($this->userRoleId == 2) {
+ if (!in_array("$controller_perifx/$action", array_merge($this->config_routers['svn_user_routers'], $this->config_routers['public'][$type]))) {
+ json1(401, 0, '无权限');
+ }
+ }
+
+ /**
+ * 6、获取数据库连接
+ */
+ if (array_key_exists('database_file', $this->config_database)) {
+ $this->config_database['database_file'] = sprintf($this->config_database['database_file'], $this->config_svn['home_path']);
+ }
+ $this->database = new Medoo($this->config_database);
+
+ /**
+ * 7、检查token是否已注销
+ */
+ $black = $this->database->get('black_token', ['token_id'], ['token' => $this->token]);
+ if ($black != null) {
+ json1(401, 0, 'token已注销');
+ }
+
+ /**
+ * 8、获取authz和passwd的配置文件信息
+ */
+ $this->GetAuthz();
+ $this->GetPasswd();
+
+ /**
+ * 9、获取payload
+ */
+ $this->payload = $payload;
+
+ /**
+ * 10、svnadmin对象
+ */
+ $this->SVNAdminGroup = new Group($this->authzContent, $this->passwdContent, $this->config_svn);
+ $this->SVNAdminRep = new Rep($this->authzContent, $this->passwdContent, $this->config_svn);
+ $this->SVNAdminUser = new User($this->authzContent, $this->passwdContent, $this->config_svn);
+
+ /**
+ * 11、检查对象
+ */
+ $this->checkService = new Check($this->config_reg);
+ }
+
+ /**
+ * 根据token获取用户信息
+ */
+ private function GetUserInfo()
+ {
+ if ($this->token == null || $this->token == '') {
+ $this->userRoleId = 0;
+ $this->userName = '';
+ return;
+ }
+
+ $array = explode('.', $this->token);
+
+ $this->userRoleId = $array[0];
+ $this->userName = $array[1];
+ }
+
+ /**
+ * 生成token
+ *
+ * @param int $userRoleId
+ * @param string $userName
+ * @return string
+ */
+ public function CreateToken($userRoleId, $userName)
+ {
+ $nowTime = time();
+
+ $startTime = $nowTime;
+
+ //配置登录凭证过期时间为6个小时
+ $endTime = $nowTime + 60 * 60 * 6;
+
+ $part1 = $userRoleId . '.' . $userName . '.' . $startTime . '.' . $endTime;
+
+ $part2 = hash_hmac('md5', $part1, $this->config_sign['signature']);
+
+ return $part1 . '.' . $part2;
+ }
+
+ /**
+ * 校验token
+ *
+ * @return void
+ */
+ private function CheckToken()
+ {
+ //判断是否为空
+ if ($this->token == null || $this->token == '') {
+ return [
+ 'code' => 401,
+ 'status' => 0,
+ 'message' => '非法请求',
+ 'data' => []
+ ];
+ }
+
+ //校验token格式
+ if (substr_count($this->token, '.') != 4) {
+ return [
+ 'code' => 401,
+ 'status' => 0,
+ 'message' => '非法请求',
+ 'data' => []
+ ];
+ }
+
+ $arr = explode('.', $this->token);
+
+ //校验token格式
+ foreach ($arr as $value) {
+ if (trim($value) == '') {
+ return [
+ 'code' => 401,
+ 'status' => 0,
+ 'message' => '非法请求',
+ 'data' => []
+ ];
+ }
+ }
+
+ //检验token内容
+ $part1 = hash_hmac('md5', $arr[0] . '.' . $arr[1] . '.' . $arr[2] . '.' . $arr[3], $this->config_sign['signature']);
+ $part2 = $arr[4];
+ if ($part1 != $part2) {
+ return [
+ 'code' => 401,
+ 'status' => 0,
+ 'message' => '非法请求',
+ 'data' => []
+ ];
+ }
+
+ //校验是否过期
+ if (time() > $arr[3]) {
+ return [
+ 'code' => 401,
+ 'status' => 0,
+ 'message' => '登陆过期',
+ 'data' => []
+ ];
+ }
+
+ return [
+ 'code' => 200,
+ 'status' => 1,
+ 'message' => '校验通过',
+ 'data' => []
+ ];
+ }
+
+ /**
+ * 从authz文件中读取内容
+ *
+ * 由于有些操作会更改authz文件内容且其它操作依赖这一实时结果 因此需要及时更新
+ */
+ public function GetAuthz()
+ {
+ $this->authzContent = file_exists($this->config_svn['svn_authz_file']) ? file_get_contents($this->config_svn['svn_authz_file']) : '';
+ }
+
+ /**
+ * 从passwd文件中读取内容
+ */
+ public function GetPasswd()
+ {
+ $this->passwdContent = file_exists($this->config_svn['svn_passwd_file']) ? file_get_contents($this->config_svn['svn_passwd_file']) : '';
+ }
+}
diff --git a/02.php/webman/app/service/check.service.php b/02.php/app/util/Check.php
similarity index 73%
rename from 02.php/webman/app/service/check.service.php
rename to 02.php/app/util/Check.php
index c9754e6..a257cf2 100644
--- a/02.php/webman/app/service/check.service.php
+++ b/02.php/app/util/Check.php
@@ -3,17 +3,17 @@
* @Author: witersen
* @Date: 2022-05-03 21:06:50
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 19:41:44
+ * @LastEditTime: 2022-05-07 00:51:06
* @Description: QQ:1801168257
*/
-class CheckService
+class Check
{
- public $config_svnadmin_reg;
+ private $config_reg;
- function __construct()
+ function __construct($config_reg)
{
- $this->config_svnadmin_reg = config('svnadmin_reg');
+ $this->config_reg = $config_reg;
}
/**
@@ -21,7 +21,7 @@ class CheckService
*/
public function CheckRepName($repName, $message = 'SVN仓库名称只能包含字母、数字、破折号、下划线、点,不能以点开头或结尾')
{
- if (preg_match($this->config_svnadmin_reg['REG_SVN_REP_NAME'], $repName) != 1) {
+ if (preg_match($this->config_reg['REG_SVN_REP_NAME'], $repName) != 1) {
return ['code' => 200, 'status' => 0, 'message' => $message, 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
@@ -32,7 +32,7 @@ class CheckService
*/
public function CheckRepUser($repUserName)
{
- if (preg_match($this->config_svnadmin_reg['REG_SVN_USER_NAME'], $repUserName) != 1) {
+ if (preg_match($this->config_reg['REG_SVN_USER_NAME'], $repUserName) != 1) {
return ['code' => 200, 'status' => 0, 'message' => 'SVN用户名只能包含字母、数字、破折号、下划线、点', 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
@@ -43,7 +43,7 @@ class CheckService
*/
public function CheckRepGroup($repGroupName)
{
- if (preg_match($this->config_svnadmin_reg['REG_SVN_GROUP_NAME'], $repGroupName) != 1) {
+ if (preg_match($this->config_reg['REG_SVN_GROUP_NAME'], $repGroupName) != 1) {
return ['code' => 200, 'status' => 0, 'message' => 'SVN分组名只能包含字母、数字、破折号、下划线、点', 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
@@ -54,7 +54,7 @@ class CheckService
*/
public function CheckMail($mail)
{
- if (preg_match_all($this->config_svnadmin_reg['REG_MAIL'], $mail) == 1) {
+ if (preg_match_all($this->config_reg['REG_MAIL'], $mail) == 1) {
return ['code' => 200, 'status' => 0, 'message' => '邮箱错误', 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
diff --git a/02.php/app/util/Config.php b/02.php/app/util/Config.php
new file mode 100644
index 0000000..fb49dc4
--- /dev/null
+++ b/02.php/app/util/Config.php
@@ -0,0 +1,45 @@
+authzFileContent = $authzFileContent;
$this->passwdFileContent = $passwdFileContent;
- $this->config_svnadmin_svn = $config_svnadmin_svn;
+ $this->config_svn = $config_svn;
}
}
diff --git a/02.php/webman/app/service/SVNAdmin/src/class/Group.class.php b/02.php/app/util/SVNAdmin/Group.php
similarity index 99%
rename from 02.php/webman/app/service/SVNAdmin/src/class/Group.class.php
rename to 02.php/app/util/SVNAdmin/Group.php
index 231779c..c870c2a 100644
--- a/02.php/webman/app/service/SVNAdmin/src/class/Group.class.php
+++ b/02.php/app/util/SVNAdmin/Group.php
@@ -3,18 +3,18 @@
* @Author: witersen
* @Date: 2022-04-27 15:55:52
* @LastEditors: witersen
- * @LastEditTime: 2022-05-04 17:14:35
+ * @LastEditTime: 2022-05-06 20:13:50
* @Description: QQ:1801168257
* @copyright: https://github.com/witersen/
*/
namespace SVNAdmin\SVN;
-class Group extends \SVNAdmin\SVN\Core
+class Group extends Core
{
- function __construct($authzFileContent, $passwdFileContent, $config_svnadmin_svn)
+ function __construct($authzFileContent, $passwdFileContent, $config_svn)
{
- parent::__construct($authzFileContent, $passwdFileContent, $config_svnadmin_svn);
+ parent::__construct($authzFileContent, $passwdFileContent, $config_svn);
}
/**
diff --git a/02.php/webman/app/service/SVNAdmin/src/class/Rep.class.php b/02.php/app/util/SVNAdmin/Rep.php
similarity index 94%
rename from 02.php/webman/app/service/SVNAdmin/src/class/Rep.class.php
rename to 02.php/app/util/SVNAdmin/Rep.php
index 821d488..f8f56e6 100644
--- a/02.php/webman/app/service/SVNAdmin/src/class/Rep.class.php
+++ b/02.php/app/util/SVNAdmin/Rep.php
@@ -12,9 +12,9 @@ namespace SVNAdmin\SVN;
class Rep extends Core
{
- function __construct($authzFileContent, $passwdFileContent, $config_svnadmin_svn)
+ function __construct($authzFileContent, $passwdFileContent, $config_svn)
{
- parent::__construct($authzFileContent, $passwdFileContent, $config_svnadmin_svn);
+ parent::__construct($authzFileContent, $passwdFileContent, $config_svn);
}
/**
@@ -802,17 +802,17 @@ class Rep extends Core
function GetRepList()
{
$repArray = [];
- $file_arr = scandir($this->config_svnadmin_svn['rep_base_path']);
+ $file_arr = scandir($this->config_svn['rep_base_path']);
foreach ($file_arr as $file_item) {
if ($file_item != '.' && $file_item != '..') {
- if (is_dir($this->config_svnadmin_svn['rep_base_path'] . $file_item)) {
- $file_arr2 = scandir($this->config_svnadmin_svn['rep_base_path'] . $file_item);
+ if (is_dir($this->config_svn['rep_base_path'] . $file_item)) {
+ $file_arr2 = scandir($this->config_svn['rep_base_path'] . $file_item);
foreach ($file_arr2 as $file_item2) {
if (($file_item2 == 'conf' || $file_item2 == 'db' || $file_item2 == 'hooks' || $file_item2 == 'locks')) {
array_push($repArray, array(
'repName' => $file_item,
- 'repUrl' => $this->config_svnadmin_svn['rep_base_path'] . $file_item,
- 'repSize' => round(FunGetDirSize($this->config_svnadmin_svn['rep_base_path'] . $file_item) / (1024 * 1024), 2),
+ 'repUrl' => $this->config_svn['rep_base_path'] . $file_item,
+ 'repSize' => round(FunGetDirSize($this->config_svn['rep_base_path'] . $file_item) / (1024 * 1024), 2),
'repCheckoutUrl' => 'svn://' . 'SERVER_DOMAIN' . '/' . $file_item,
));
break;
@@ -830,11 +830,11 @@ class Rep extends Core
function GetSimpleRepList()
{
$repArray = [];
- $file_arr = scandir($this->config_svnadmin_svn['rep_base_path']);
+ $file_arr = scandir($this->config_svn['rep_base_path']);
foreach ($file_arr as $file_item) {
if ($file_item != '.' && $file_item != '..') {
- if (is_dir($this->config_svnadmin_svn['rep_base_path'] . $file_item)) {
- $file_arr2 = scandir($this->config_svnadmin_svn['rep_base_path'] . $file_item);
+ if (is_dir($this->config_svn['rep_base_path'] . $file_item)) {
+ $file_arr2 = scandir($this->config_svn['rep_base_path'] . $file_item);
foreach ($file_arr2 as $file_item2) {
if (($file_item2 == 'conf' || $file_item2 == 'db' || $file_item2 == 'hooks' || $file_item2 == 'locks')) {
array_push($repArray, $file_item);
@@ -853,7 +853,7 @@ class Rep extends Core
function InitRepStruct($templetePath, $repPath, $initUser = 'SVNAdmin', $initPass = 'SVNAdmin', $message = 'Initial structure')
{
$cmd = sprintf("svn import '%s' 'file:///%s' --quiet --username '%s' --password '%s' --message '%s'", $templetePath, $repPath, $initUser, $initPass, $message);
- passthru($cmd);
+ FunShellExec($cmd);
}
/**
@@ -872,11 +872,11 @@ class Rep extends Core
*/
function GetRepInfo($repName)
{
- $repPath = $this->config_svnadmin_svn['rep_base_path'] . $repName;
+ $repPath = $this->config_svn['rep_base_path'] . $repName;
$svnadminInfoCmd = sprintf("svnadmin info '%s'", $repPath);
- $cmdResult = shellPassthru($svnadminInfoCmd);
+ $cmdResult = FunShellExec($svnadminInfoCmd);
$cmdResult = $cmdResult['result'];
preg_match_all($this->REG_REP_INFO, $cmdResult, $svnadminInfoPreg);
@@ -893,11 +893,11 @@ class Rep extends Core
*/
function GetRepTree($repName)
{
- $repPath = $this->config_svnadmin_svn['rep_base_path'] . $repName;
+ $repPath = $this->config_svn['rep_base_path'] . $repName;
$svnadminInfoCmd = sprintf("svnlook tree '%s'", $repPath);
- $cmdResult = shellPassthru($svnadminInfoCmd);
+ $cmdResult = FunShellExec($svnadminInfoCmd);
$cmdResult = $cmdResult['result'];
- // $cmdResult = passthru($svnadminInfoCmd);
+ // $cmdResult = FunShellExec($svnadminInfoCmd);
$treeArray = explode("\n", $cmdResult);
//去除数组中的空字符串键值 通常为最后一项
$treeArray = array_filter($treeArray, 'FunArrayValueFilter');
@@ -1166,7 +1166,7 @@ class Rep extends Core
function CheckRepExist($repName, $message = '仓库已经存在')
{
clearstatcache();
- if (is_dir($this->config_svnadmin_svn['rep_base_path'] . $repName)) {
+ if (is_dir($this->config_svn['rep_base_path'] . $repName)) {
return ['code' => 200, 'status' => 0, 'message' => $message, 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
@@ -1178,7 +1178,7 @@ class Rep extends Core
function CheckRepCreate($repName, $message = '仓库创建失败')
{
clearstatcache();
- if (!is_dir($this->config_svnadmin_svn['rep_base_path'] . $repName)) {
+ if (!is_dir($this->config_svn['rep_base_path'] . $repName)) {
return ['code' => 200, 'status' => 0, 'message' => $message, 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
@@ -1190,7 +1190,7 @@ class Rep extends Core
function CheckRepDelete($repName, $message = '仓库删除失败')
{
clearstatcache();
- if (is_dir($this->config_svnadmin_svn['rep_base_path'] . $repName)) {
+ if (is_dir($this->config_svn['rep_base_path'] . $repName)) {
return ['code' => 200, 'status' => 0, 'message' => $message, 'data' => []];
}
return ['code' => 200, 'status' => 1, 'message' => '', 'data' => []];
@@ -1201,8 +1201,8 @@ class Rep extends Core
*/
function GetRepRev($repName)
{
- $cmd = sprintf("svnadmin info '%s' | grep 'Revisions' | awk '{print $2}'", $this->config_svnadmin_svn['rep_base_path'] . $repName);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnadmin info '%s' | grep 'Revisions' | awk '{print $2}'", $this->config_svn['rep_base_path'] . $repName);
+ $result = FunShellExec($cmd);
return (int)$result['result'];
}
@@ -1211,8 +1211,8 @@ class Rep extends Core
*/
function GetRepDetail($repName)
{
- $cmd = sprintf("svnadmin info '%s'", $this->config_svnadmin_svn['rep_base_path'] . $repName);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnadmin info '%s'", $this->config_svn['rep_base_path'] . $repName);
+ $result = FunShellExec($cmd);
return $result['result'];
}
@@ -1225,8 +1225,8 @@ class Rep extends Core
*/
function GetRepRevFileSize($repName, $filePath)
{
- $cmd = sprintf("svnlook filesize '%s' '%s'", $this->config_svnadmin_svn['rep_base_path'] . $repName, $filePath);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnlook filesize '%s' '%s'", $this->config_svn['rep_base_path'] . $repName, $filePath);
+ $result = FunShellExec($cmd);
$size = (int)$result['result'];
return FunFormatSize($size);
}
@@ -1236,8 +1236,8 @@ class Rep extends Core
*/
function GetRepFileRev($repName, $filePath)
{
- $cmd = sprintf("svnlook history --limit 1 '%s' '%s'", $this->config_svnadmin_svn['rep_base_path'] . $repName, $filePath);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnlook history --limit 1 '%s' '%s'", $this->config_svn['rep_base_path'] . $repName, $filePath);
+ $result = FunShellExec($cmd);
$result = $result['result'];
$resultArray = explode("\n", $result);
$content = preg_replace("/\s{2,}/", ' ', $resultArray[2]);
@@ -1250,8 +1250,8 @@ class Rep extends Core
*/
function GetRepFileAuthor($repName, $rev)
{
- $cmd = sprintf("svnlook author -r %s '%s'", $rev, $this->config_svnadmin_svn['rep_base_path'] . $repName);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnlook author -r %s '%s'", $rev, $this->config_svn['rep_base_path'] . $repName);
+ $result = FunShellExec($cmd);
return $result['result'];
}
@@ -1260,8 +1260,8 @@ class Rep extends Core
*/
function GetRepFileDate($repName, $rev)
{
- $cmd = sprintf("svnlook date -r %s '%s'", $rev, $this->config_svnadmin_svn['rep_base_path'] . $repName);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnlook date -r %s '%s'", $rev, $this->config_svn['rep_base_path'] . $repName);
+ $result = FunShellExec($cmd);
return $result['result'];
}
@@ -1270,8 +1270,8 @@ class Rep extends Core
*/
function GetRepFileLog($repName, $rev)
{
- $cmd = sprintf("svnlook log -r %s '%s'", $rev, $this->config_svnadmin_svn['rep_base_path'] . $repName);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnlook log -r %s '%s'", $rev, $this->config_svn['rep_base_path'] . $repName);
+ $result = FunShellExec($cmd);
return $result['result'];
}
@@ -1282,8 +1282,8 @@ class Rep extends Core
*/
function RepDump($repName, $backupName)
{
- $cmd = sprintf('svnadmin dump %s --quiet > %s', $this->config_svnadmin_svn['rep_base_path'] . $repName, $this->config_svnadmin_svn['backup_base_path'] . $backupName);
- passthru($cmd);
+ $cmd = sprintf('svnadmin dump %s --quiet > %s', $this->config_svn['rep_base_path'] . $repName, $this->config_svn['backup_base_path'] . $backupName);
+ FunShellExec($cmd);
}
/**
@@ -1291,8 +1291,8 @@ class Rep extends Core
*/
function DelRepBackup($fileName)
{
- $cmd = sprintf("cd '%s' && rm -f './%s'", $this->config_svnadmin_svn['backup_base_path'], $fileName);
- passthru($cmd);
+ $cmd = sprintf("cd '%s' && rm -f './%s'", $this->config_svn['backup_base_path'], $fileName);
+ FunShellExec($cmd);
}
/**
@@ -1300,8 +1300,8 @@ class Rep extends Core
*/
function RepLoad($repName, $fileName)
{
- $cmd = sprintf("svnadmin load --quiet '%s' < '%s'", $this->config_svnadmin_svn['rep_base_path'] . $repName, $this->config_svnadmin_svn['backup_base_path'] . $fileName);
- $result = shellPassthru($cmd);
+ $cmd = sprintf("svnadmin load --quiet '%s' < '%s'", $this->config_svn['rep_base_path'] . $repName, $this->config_svn['backup_base_path'] . $fileName);
+ $result = FunShellExec($cmd);
return $result;
}
@@ -1311,7 +1311,7 @@ class Rep extends Core
function CheckSvnUserPathAutzh($checkoutHost, $repName, $repPath, $svnUserName, $svnUserPass)
{
$cmd = sprintf("svn list '%s' --username '%s' --password '%s' --no-auth-cache --non-interactive --trust-server-cert", $checkoutHost . '/' . $repName . $repPath, $svnUserName, $svnUserPass);
- $result = shellPassthru($cmd);
+ $result = FunShellExec($cmd);
if ($result['resultCode'] != 0) {
//: Authentication error from server: Password incorrect
diff --git a/02.php/webman/app/service/SVNAdmin/src/class/User.class.php b/02.php/app/util/SVNAdmin/User.php
similarity index 99%
rename from 02.php/webman/app/service/SVNAdmin/src/class/User.class.php
rename to 02.php/app/util/SVNAdmin/User.php
index bd3cd31..75b9ac8 100644
--- a/02.php/webman/app/service/SVNAdmin/src/class/User.class.php
+++ b/02.php/app/util/SVNAdmin/User.php
@@ -12,9 +12,9 @@ namespace SVNAdmin\SVN;
class User extends Core
{
- function __construct($authzFileContent, $passwdFileContent, $config_svnadmin_svn)
+ function __construct($authzFileContent, $passwdFileContent, $config_svn)
{
- parent::__construct($authzFileContent, $passwdFileContent, $config_svnadmin_svn);
+ parent::__construct($authzFileContent, $passwdFileContent, $config_svn);
}
/**
diff --git a/02.php/config/daemon.php b/02.php/config/daemon.php
new file mode 100644
index 0000000..47c5227
--- /dev/null
+++ b/02.php/config/daemon.php
@@ -0,0 +1,60 @@
+ '127.0.0.1',
+
+ /**
+ * 程序与守护进程通信的本地端口
+ * 如与现有业务端口冲突 请自行修改
+ */
+ 'IPC_PORT' => 6666,
+
+ /**
+ * socket_read 和 socket_write 的最大传输字节
+ * 如果没有需要 8192 字节已经极大的满足需求
+ */
+ 'SOCKET_READ_LENGTH' => 8192,
+ 'SOCKET_WRITE_LENGTH' => 8192,
+
+ /**
+ * socket 处理并发的最大队列长度
+ */
+ 'SOCKET_LISTEN_BACKLOG' => 2000,
+
+ /**
+ * 当前程序支持的最低PHP版本
+ */
+ 'Required_PHP_VERSION' => '5.5',
+
+ /**
+ * CLI程序需要解除禁止的函数
+ */
+ 'CLI_NEEDED_FUNCTION' => [
+ 'pcntl_fork',
+ 'pcntl_signal',
+ 'pcntl_wait',
+ 'shell_exec'
+ ],
+
+ /**
+ * FPM模式需要解除禁止的函数
+ */
+ 'FPM_NEEDED_FUNCTION' => [],
+
+];
diff --git a/02.php/config/database.php b/02.php/config/database.php
new file mode 100644
index 0000000..b2669fa
--- /dev/null
+++ b/02.php/config/database.php
@@ -0,0 +1,43 @@
+ 'mysql',
+ 'server' => 'test.demo.com',
+ 'database_name' => 'svnadmin',
+ 'username' => 'useranme',
+ 'password' => 'password',
+ 'charset' => 'utf8mb4',
+ 'collation' => 'utf8mb4_general_ci',
+ 'port' => 3306,
+ 'prefix' => '',
+ 'logging' => false,
+ 'option' => [
+ PDO::ATTR_CASE => PDO::CASE_NATURAL
+ ],
+ 'command' => [
+ 'SET SQL_MODE=ANSI_QUOTES'
+ ]
+];
+
+/**
+ * for SQLite
+ * config from Medoo 1.7.10
+ *
+ * %s 为占位符 无需修改
+ */
+
+// return [
+// 'database_type' => 'sqlite',
+// 'database_file' => '%ssvnadmin.db'
+// ];
diff --git a/02.php/webman/config/svnadmin_reg.php b/02.php/config/reg.php
similarity index 100%
rename from 02.php/webman/config/svnadmin_reg.php
rename to 02.php/config/reg.php
diff --git a/02.php/config/router.php b/02.php/config/router.php
new file mode 100644
index 0000000..c7f5a10
--- /dev/null
+++ b/02.php/config/router.php
@@ -0,0 +1,43 @@
+ [
+ 'web' => [
+ 'Common/Login',
+ 'Common/GetVeryfyCode'
+ ],
+ 'mini' => []
+ ],
+
+ /**
+ * SVN用户有权限路由
+ */
+ 'svn_user_routers' => [
+ 'Svnrep/GetSvnUserRepList',
+ 'Svnrep/GetUserRepCon',
+
+ 'Common/Logout',
+
+ 'Svn/GetCheckout',
+ 'Svn/GetStatus',
+
+ 'Personal/EditSvnUserPass',
+ ],
+];
diff --git a/02.php/webman/config/svnadmin_sign.php b/02.php/config/sign.php
similarity index 100%
rename from 02.php/webman/config/svnadmin_sign.php
rename to 02.php/config/sign.php
diff --git a/02.php/webman/config/svnadmin_svn.php b/02.php/config/svn.php
similarity index 90%
rename from 02.php/webman/config/svnadmin_svn.php
rename to 02.php/config/svn.php
index 2441719..e73ab0c 100644
--- a/02.php/webman/config/svnadmin_svn.php
+++ b/02.php/config/svn.php
@@ -3,13 +3,12 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:06
* @LastEditors: witersen
- * @LastEditTime: 2022-05-03 22:19:27
+ * @LastEditTime: 2022-05-07 01:25:25
* @Description: QQ:1801168257
*/
/**
- * 如果要修改
- * 需要在安装软件之前修改该值 安装过程中会自动读取并操作
+ * 如果要修改安装路径 ,请在安装本程序前修改$home_path的值,安装程序后不支持修改
*/
$home_path = '/home/svnadmin/';
diff --git a/02.php/webman/config/svnadmin_update.php b/02.php/config/update.php
similarity index 59%
rename from 02.php/webman/config/svnadmin_update.php
rename to 02.php/config/update.php
index a7dd202..895805a 100644
--- a/02.php/webman/config/svnadmin_update.php
+++ b/02.php/config/update.php
@@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:06
* @LastEditors: witersen
- * @LastEditTime: 2022-05-03 16:22:03
+ * @LastEditTime: 2022-05-07 01:13:58
* @Description: QQ:1801168257
*/
@@ -16,7 +16,3 @@ return [
'https://raw.githubusercontent.com/witersen/update/master/SvnAdmin/update.json'
]
];
-// define('UPDATE_SERVER', serialize([
-// 'https://gitee.com/witersen/update/raw/master/SvnAdmin/update.json',
-// 'https://raw.githubusercontent.com/witersen/update/master/SvnAdmin/update.json'
-// ]));
diff --git a/02.php/webman/config/svnadmin_version.php b/02.php/config/version.php
similarity index 100%
rename from 02.php/webman/config/svnadmin_version.php
rename to 02.php/config/version.php
diff --git a/02.php/extension/Medoo-1.7.10/src/Medoo.php b/02.php/extension/Medoo-1.7.10/src/Medoo.php
new file mode 100644
index 0000000..0164591
--- /dev/null
+++ b/02.php/extension/Medoo-1.7.10/src/Medoo.php
@@ -0,0 +1,1852 @@
+type = strtolower($options[ 'database_type' ]);
+
+ if ($this->type === 'mariadb')
+ {
+ $this->type = 'mysql';
+ }
+ }
+
+ if (isset($options[ 'prefix' ]))
+ {
+ $this->prefix = $options[ 'prefix' ];
+ }
+
+ if (isset($options[ 'logging' ]) && is_bool($options[ 'logging' ]))
+ {
+ $this->logging = $options[ 'logging' ];
+ }
+
+ $option = isset($options[ 'option' ]) ? $options[ 'option' ] : [];
+ $commands = (isset($options[ 'command' ]) && is_array($options[ 'command' ])) ? $options[ 'command' ] : [];
+
+ switch ($this->type)
+ {
+ case 'mysql':
+ // Make MySQL using standard quoted identifier
+ $commands[] = 'SET SQL_MODE=ANSI_QUOTES';
+
+ break;
+
+ case 'mssql':
+ // Keep MSSQL QUOTED_IDENTIFIER is ON for standard quoting
+ $commands[] = 'SET QUOTED_IDENTIFIER ON';
+
+ // Make ANSI_NULLS is ON for NULL value
+ $commands[] = 'SET ANSI_NULLS ON';
+
+ break;
+ }
+
+ if (isset($options[ 'pdo' ]))
+ {
+ if (!$options[ 'pdo' ] instanceof PDO)
+ {
+ throw new InvalidArgumentException('Invalid PDO object supplied');
+ }
+
+ $this->pdo = $options[ 'pdo' ];
+
+ foreach ($commands as $value)
+ {
+ $this->pdo->exec($value);
+ }
+
+ return;
+ }
+
+ if (isset($options[ 'dsn' ]))
+ {
+ if (is_array($options[ 'dsn' ]) && isset($options[ 'dsn' ][ 'driver' ]))
+ {
+ $attr = $options[ 'dsn' ];
+ }
+ else
+ {
+ throw new InvalidArgumentException('Invalid DSN option supplied');
+ }
+ }
+ else
+ {
+ if (
+ isset($options[ 'port' ]) &&
+ is_int($options[ 'port' ] * 1)
+ )
+ {
+ $port = $options[ 'port' ];
+ }
+
+ $is_port = isset($port);
+
+ switch ($this->type)
+ {
+ case 'mysql':
+ $attr = [
+ 'driver' => 'mysql',
+ 'dbname' => $options[ 'database_name' ]
+ ];
+
+ if (isset($options[ 'socket' ]))
+ {
+ $attr[ 'unix_socket' ] = $options[ 'socket' ];
+ }
+ else
+ {
+ $attr[ 'host' ] = $options[ 'server' ];
+
+ if ($is_port)
+ {
+ $attr[ 'port' ] = $port;
+ }
+ }
+
+ break;
+
+ case 'pgsql':
+ $attr = [
+ 'driver' => 'pgsql',
+ 'host' => $options[ 'server' ],
+ 'dbname' => $options[ 'database_name' ]
+ ];
+
+ if ($is_port)
+ {
+ $attr[ 'port' ] = $port;
+ }
+
+ break;
+
+ case 'sybase':
+ $attr = [
+ 'driver' => 'dblib',
+ 'host' => $options[ 'server' ],
+ 'dbname' => $options[ 'database_name' ]
+ ];
+
+ if ($is_port)
+ {
+ $attr[ 'port' ] = $port;
+ }
+
+ break;
+
+ case 'oracle':
+ $attr = [
+ 'driver' => 'oci',
+ 'dbname' => $options[ 'server' ] ?
+ '//' . $options[ 'server' ] . ($is_port ? ':' . $port : ':1521') . '/' . $options[ 'database_name' ] :
+ $options[ 'database_name' ]
+ ];
+
+ if (isset($options[ 'charset' ]))
+ {
+ $attr[ 'charset' ] = $options[ 'charset' ];
+ }
+
+ break;
+
+ case 'mssql':
+ if (isset($options[ 'driver' ]) && $options[ 'driver' ] === 'dblib')
+ {
+ $attr = [
+ 'driver' => 'dblib',
+ 'host' => $options[ 'server' ] . ($is_port ? ':' . $port : ''),
+ 'dbname' => $options[ 'database_name' ]
+ ];
+
+ if (isset($options[ 'appname' ]))
+ {
+ $attr[ 'appname' ] = $options[ 'appname' ];
+ }
+
+ if (isset($options[ 'charset' ]))
+ {
+ $attr[ 'charset' ] = $options[ 'charset' ];
+ }
+ }
+ else
+ {
+ $attr = [
+ 'driver' => 'sqlsrv',
+ 'Server' => $options[ 'server' ] . ($is_port ? ',' . $port : ''),
+ 'Database' => $options[ 'database_name' ]
+ ];
+
+ if (isset($options[ 'appname' ]))
+ {
+ $attr[ 'APP' ] = $options[ 'appname' ];
+ }
+
+ $config = [
+ 'ApplicationIntent',
+ 'AttachDBFileName',
+ 'Authentication',
+ 'ColumnEncryption',
+ 'ConnectionPooling',
+ 'Encrypt',
+ 'Failover_Partner',
+ 'KeyStoreAuthentication',
+ 'KeyStorePrincipalId',
+ 'KeyStoreSecret',
+ 'LoginTimeout',
+ 'MultipleActiveResultSets',
+ 'MultiSubnetFailover',
+ 'Scrollable',
+ 'TraceFile',
+ 'TraceOn',
+ 'TransactionIsolation',
+ 'TransparentNetworkIPResolution',
+ 'TrustServerCertificate',
+ 'WSID',
+ ];
+
+ foreach ($config as $value)
+ {
+ $keyname = strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $value));
+
+ if (isset($options[ $keyname ]))
+ {
+ $attr[ $value ] = $options[ $keyname ];
+ }
+ }
+ }
+
+ break;
+
+ case 'sqlite':
+ $attr = [
+ 'driver' => 'sqlite',
+ $options[ 'database_file' ]
+ ];
+
+ break;
+ }
+ }
+
+ if (!isset($attr))
+ {
+ throw new InvalidArgumentException('Incorrect connection options');
+ }
+
+ $driver = $attr[ 'driver' ];
+
+ if (!in_array($driver, PDO::getAvailableDrivers()))
+ {
+ throw new InvalidArgumentException("Unsupported PDO driver: {$driver}");
+ }
+
+ unset($attr[ 'driver' ]);
+
+ $stack = [];
+
+ foreach ($attr as $key => $value)
+ {
+ $stack[] = is_int($key) ? $value : $key . '=' . $value;
+ }
+
+ $dsn = $driver . ':' . implode(';', $stack);
+
+ if (
+ in_array($this->type, ['mysql', 'pgsql', 'sybase', 'mssql']) &&
+ isset($options[ 'charset' ])
+ )
+ {
+ $commands[] = "SET NAMES '{$options[ 'charset' ]}'" . (
+ $this->type === 'mysql' && isset($options[ 'collation' ]) ?
+ " COLLATE '{$options[ 'collation' ]}'" : ''
+ );
+ }
+
+ $this->dsn = $dsn;
+
+ try {
+ $this->pdo = new PDO(
+ $dsn,
+ isset($options[ 'username' ]) ? $options[ 'username' ] : null,
+ isset($options[ 'password' ]) ? $options[ 'password' ] : null,
+ $option
+ );
+
+ foreach ($commands as $value)
+ {
+ $this->pdo->exec($value);
+ }
+ }
+ catch (PDOException $e) {
+ throw new PDOException($e->getMessage());
+ }
+ }
+
+ public function query($query, $map = [])
+ {
+ $raw = $this->raw($query, $map);
+
+ $query = $this->buildRaw($raw, $map);
+
+ return $this->exec($query, $map);
+ }
+
+ public function exec($query, $map = [])
+ {
+ $this->statement = null;
+
+ if ($this->debug_mode)
+ {
+ echo $this->generate($query, $map);
+
+ $this->debug_mode = false;
+
+ return false;
+ }
+
+ if ($this->logging)
+ {
+ $this->logs[] = [$query, $map];
+ }
+ else
+ {
+ $this->logs = [[$query, $map]];
+ }
+
+ $statement = $this->pdo->prepare($query);
+
+ if (!$statement)
+ {
+ $this->errorInfo = $this->pdo->errorInfo();
+ $this->statement = null;
+
+ return false;
+ }
+
+ $this->statement = $statement;
+
+ foreach ($map as $key => $value)
+ {
+ $statement->bindValue($key, $value[ 0 ], $value[ 1 ]);
+ }
+
+ $execute = $statement->execute();
+
+ $this->errorInfo = $statement->errorInfo();
+
+ if (!$execute)
+ {
+ $this->statement = null;
+ }
+
+ return $statement;
+ }
+
+ protected function generate($query, $map)
+ {
+ $identifier = [
+ 'mysql' => '`$1`',
+ 'mssql' => '[$1]'
+ ];
+
+ $query = preg_replace(
+ '/"([a-zA-Z0-9_]+)"/i',
+ isset($identifier[ $this->type ]) ? $identifier[ $this->type ] : '"$1"',
+ $query
+ );
+
+ foreach ($map as $key => $value)
+ {
+ if ($value[ 1 ] === PDO::PARAM_STR)
+ {
+ $replace = $this->quote($value[ 0 ]);
+ }
+ elseif ($value[ 1 ] === PDO::PARAM_NULL)
+ {
+ $replace = 'NULL';
+ }
+ elseif ($value[ 1 ] === PDO::PARAM_LOB)
+ {
+ $replace = '{LOB_DATA}';
+ }
+ else
+ {
+ $replace = $value[ 0 ];
+ }
+
+ $query = str_replace($key, $replace, $query);
+ }
+
+ return $query;
+ }
+
+ public static function raw($string, $map = [])
+ {
+ $raw = new Raw();
+
+ $raw->map = $map;
+ $raw->value = $string;
+
+ return $raw;
+ }
+
+ protected function isRaw($object)
+ {
+ return $object instanceof Raw;
+ }
+
+ protected function buildRaw($raw, &$map)
+ {
+ if (!$this->isRaw($raw))
+ {
+ return false;
+ }
+
+ $query = preg_replace_callback(
+ '/(([`\']).*?)?((FROM|TABLE|INTO|UPDATE|JOIN)\s*)?\<(([a-zA-Z0-9_]+)(\.[a-zA-Z0-9_]+)?)\>(.*?\2)?/i',
+ function ($matches)
+ {
+ if (!empty($matches[ 2 ]) && isset($matches[ 8 ]))
+ {
+ return $matches[ 0 ];
+ }
+
+ if (!empty($matches[ 4 ]))
+ {
+ return $matches[ 1 ] . $matches[ 4 ] . ' ' . $this->tableQuote($matches[ 5 ]);
+ }
+
+ return $matches[ 1 ] . $this->columnQuote($matches[ 5 ]);
+ },
+ $raw->value);
+
+ $raw_map = $raw->map;
+
+ if (!empty($raw_map))
+ {
+ foreach ($raw_map as $key => $value)
+ {
+ $map[ $key ] = $this->typeMap($value, gettype($value));
+ }
+ }
+
+ return $query;
+ }
+
+ public function quote($string)
+ {
+ return $this->pdo->quote($string);
+ }
+
+ protected function tableQuote($table)
+ {
+ if (!preg_match('/^[a-zA-Z0-9_]+$/i', $table))
+ {
+ throw new InvalidArgumentException("Incorrect table name \"$table\"");
+ }
+
+ return '"' . $this->prefix . $table . '"';
+ }
+
+ protected function mapKey()
+ {
+ return ':MeDoO_' . $this->guid++ . '_mEdOo';
+ }
+
+ protected function typeMap($value, $type)
+ {
+ $map = [
+ 'NULL' => PDO::PARAM_NULL,
+ 'integer' => PDO::PARAM_INT,
+ 'double' => PDO::PARAM_STR,
+ 'boolean' => PDO::PARAM_BOOL,
+ 'string' => PDO::PARAM_STR,
+ 'object' => PDO::PARAM_STR,
+ 'resource' => PDO::PARAM_LOB
+ ];
+
+ if ($type === 'boolean')
+ {
+ $value = ($value ? '1' : '0');
+ }
+ elseif ($type === 'NULL')
+ {
+ $value = null;
+ }
+
+ return [$value, $map[ $type ]];
+ }
+
+ protected function columnQuote($string)
+ {
+ if (!preg_match('/^[a-zA-Z0-9_]+(\.?[a-zA-Z0-9_]+)?$/i', $string))
+ {
+ throw new InvalidArgumentException("Incorrect column name \"$string\"");
+ }
+
+ if (strpos($string, '.') !== false)
+ {
+ return '"' . $this->prefix . str_replace('.', '"."', $string) . '"';
+ }
+
+ return '"' . $string . '"';
+ }
+
+ protected function columnPush(&$columns, &$map, $root, $is_join = false)
+ {
+ if ($columns === '*')
+ {
+ return $columns;
+ }
+
+ $stack = [];
+
+ if (is_string($columns))
+ {
+ $columns = [$columns];
+ }
+
+ foreach ($columns as $key => $value)
+ {
+ if (!is_int($key) && is_array($value) && $root && count(array_keys($columns)) === 1)
+ {
+ $stack[] = $this->columnQuote($key);
+
+ $stack[] = $this->columnPush($value, $map, false, $is_join);
+ }
+ elseif (is_array($value))
+ {
+ $stack[] = $this->columnPush($value, $map, false, $is_join);
+ }
+ elseif (!is_int($key) && $raw = $this->buildRaw($value, $map))
+ {
+ preg_match('/(?[a-zA-Z0-9_\.]+)(\s*\[(?(String|Bool|Int|Number))\])?/i', $key, $match);
+
+ $stack[] = $raw . ' AS ' . $this->columnQuote($match[ 'column' ]);
+ }
+ elseif (is_int($key) && is_string($value))
+ {
+ if ($is_join && strpos($value, '*') !== false)
+ {
+ throw new InvalidArgumentException('Cannot use table.* to select all columns while joining table');
+ }
+
+ preg_match('/(?[a-zA-Z0-9_\.]+)(?:\s*\((?[a-zA-Z0-9_]+)\))?(?:\s*\[(?(?:String|Bool|Int|Number|Object|JSON))\])?/i', $value, $match);
+
+ if (!empty($match[ 'alias' ]))
+ {
+ $stack[] = $this->columnQuote($match[ 'column' ]) . ' AS ' . $this->columnQuote($match[ 'alias' ]);
+
+ $columns[ $key ] = $match[ 'alias' ];
+
+ if (!empty($match[ 'type' ]))
+ {
+ $columns[ $key ] .= ' [' . $match[ 'type' ] . ']';
+ }
+ }
+ else
+ {
+ $stack[] = $this->columnQuote($match[ 'column' ]);
+ }
+ }
+ }
+
+ return implode(',', $stack);
+ }
+
+ protected function arrayQuote($array)
+ {
+ $stack = [];
+
+ foreach ($array as $value)
+ {
+ $stack[] = is_int($value) ? $value : $this->pdo->quote($value);
+ }
+
+ return implode(',', $stack);
+ }
+
+ protected function innerConjunct($data, $map, $conjunctor, $outer_conjunctor)
+ {
+ $stack = [];
+
+ foreach ($data as $value)
+ {
+ $stack[] = '(' . $this->dataImplode($value, $map, $conjunctor) . ')';
+ }
+
+ return implode($outer_conjunctor . ' ', $stack);
+ }
+
+ protected function dataImplode($data, &$map, $conjunctor)
+ {
+ $stack = [];
+
+ foreach ($data as $key => $value)
+ {
+ $type = gettype($value);
+
+ if (
+ $type === 'array' &&
+ preg_match("/^(AND|OR)(\s+#.*)?$/", $key, $relation_match)
+ )
+ {
+ $relationship = $relation_match[ 1 ];
+
+ $stack[] = $value !== array_keys(array_keys($value)) ?
+ '(' . $this->dataImplode($value, $map, ' ' . $relationship) . ')' :
+ '(' . $this->innerConjunct($value, $map, ' ' . $relationship, $conjunctor) . ')';
+
+ continue;
+ }
+
+ $map_key = $this->mapKey();
+
+ if (
+ is_int($key) &&
+ preg_match('/([a-zA-Z0-9_\.]+)\[(?\>\=?|\<\=?|\!?\=)\]([a-zA-Z0-9_\.]+)/i', $value, $match)
+ )
+ {
+ $stack[] = $this->columnQuote($match[ 1 ]) . ' ' . $match[ 'operator' ] . ' ' . $this->columnQuote($match[ 3 ]);
+ }
+ else
+ {
+ preg_match('/([a-zA-Z0-9_\.]+)(\[(?\>\=?|\<\=?|\!|\<\>|\>\<|\!?~|REGEXP)\])?/i', $key, $match);
+ $column = $this->columnQuote($match[ 1 ]);
+
+ if (isset($match[ 'operator' ]))
+ {
+ $operator = $match[ 'operator' ];
+
+ if (in_array($operator, ['>', '>=', '<', '<=']))
+ {
+ $condition = $column . ' ' . $operator . ' ';
+
+ if (is_numeric($value))
+ {
+ $condition .= $map_key;
+ $map[ $map_key ] = [$value, is_float($value) ? PDO::PARAM_STR : PDO::PARAM_INT];
+ }
+ elseif ($raw = $this->buildRaw($value, $map))
+ {
+ $condition .= $raw;
+ }
+ else
+ {
+ $condition .= $map_key;
+ $map[ $map_key ] = [$value, PDO::PARAM_STR];
+ }
+
+ $stack[] = $condition;
+ }
+ elseif ($operator === '!')
+ {
+ switch ($type)
+ {
+ case 'NULL':
+ $stack[] = $column . ' IS NOT NULL';
+ break;
+
+ case 'array':
+ $placeholders = [];
+
+ foreach ($value as $index => $item)
+ {
+ $stack_key = $map_key . $index . '_i';
+
+ $placeholders[] = $stack_key;
+ $map[ $stack_key ] = $this->typeMap($item, gettype($item));
+ }
+
+ $stack[] = $column . ' NOT IN (' . implode(', ', $placeholders) . ')';
+ break;
+
+ case 'object':
+ if ($raw = $this->buildRaw($value, $map))
+ {
+ $stack[] = $column . ' != ' . $raw;
+ }
+ break;
+
+ case 'integer':
+ case 'double':
+ case 'boolean':
+ case 'string':
+ $stack[] = $column . ' != ' . $map_key;
+ $map[ $map_key ] = $this->typeMap($value, $type);
+ break;
+ }
+ }
+ elseif ($operator === '~' || $operator === '!~')
+ {
+ if ($type !== 'array')
+ {
+ $value = [ $value ];
+ }
+
+ $connector = ' OR ';
+ $data = array_values($value);
+
+ if (is_array($data[ 0 ]))
+ {
+ if (isset($value[ 'AND' ]) || isset($value[ 'OR' ]))
+ {
+ $connector = ' ' . array_keys($value)[ 0 ] . ' ';
+ $value = $data[ 0 ];
+ }
+ }
+
+ $like_clauses = [];
+
+ foreach ($value as $index => $item)
+ {
+ $item = strval($item);
+
+ if (!preg_match('/(\[.+\]|[\*\?\!\%#^-_]|%.+|.+%)/', $item))
+ {
+ $item = '%' . $item . '%';
+ }
+
+ $like_clauses[] = $column . ($operator === '!~' ? ' NOT' : '') . ' LIKE ' . $map_key . 'L' . $index;
+ $map[ $map_key . 'L' . $index ] = [$item, PDO::PARAM_STR];
+ }
+
+ $stack[] = '(' . implode($connector, $like_clauses) . ')';
+ }
+ elseif ($operator === '<>' || $operator === '><')
+ {
+ if ($type === 'array')
+ {
+ if ($operator === '><')
+ {
+ $column .= ' NOT';
+ }
+
+ $stack[] = '(' . $column . ' BETWEEN ' . $map_key . 'a AND ' . $map_key . 'b)';
+
+ $data_type = (is_numeric($value[ 0 ]) && is_numeric($value[ 1 ])) ? PDO::PARAM_INT : PDO::PARAM_STR;
+
+ $map[ $map_key . 'a' ] = [$value[ 0 ], $data_type];
+ $map[ $map_key . 'b' ] = [$value[ 1 ], $data_type];
+ }
+ }
+ elseif ($operator === 'REGEXP')
+ {
+ $stack[] = $column . ' REGEXP ' . $map_key;
+ $map[ $map_key ] = [$value, PDO::PARAM_STR];
+ }
+ }
+ else
+ {
+ switch ($type)
+ {
+ case 'NULL':
+ $stack[] = $column . ' IS NULL';
+ break;
+
+ case 'array':
+ $placeholders = [];
+
+ foreach ($value as $index => $item)
+ {
+ $stack_key = $map_key . $index . '_i';
+
+ $placeholders[] = $stack_key;
+ $map[ $stack_key ] = $this->typeMap($item, gettype($item));
+ }
+
+ $stack[] = $column . ' IN (' . implode(', ', $placeholders) . ')';
+ break;
+
+ case 'object':
+ if ($raw = $this->buildRaw($value, $map))
+ {
+ $stack[] = $column . ' = ' . $raw;
+ }
+ break;
+
+ case 'integer':
+ case 'double':
+ case 'boolean':
+ case 'string':
+ $stack[] = $column . ' = ' . $map_key;
+ $map[ $map_key ] = $this->typeMap($value, $type);
+ break;
+ }
+ }
+ }
+ }
+
+ return implode($conjunctor . ' ', $stack);
+ }
+
+ protected function whereClause($where, &$map)
+ {
+ $where_clause = '';
+
+ if (is_array($where))
+ {
+ $where_keys = array_keys($where);
+
+ $conditions = array_diff_key($where, array_flip(
+ ['GROUP', 'ORDER', 'HAVING', 'LIMIT', 'LIKE', 'MATCH']
+ ));
+
+ if (!empty($conditions))
+ {
+ $where_clause = ' WHERE ' . $this->dataImplode($conditions, $map, ' AND');
+ }
+
+ if (isset($where[ 'MATCH' ]) && $this->type === 'mysql')
+ {
+ $MATCH = $where[ 'MATCH' ];
+
+ if (is_array($MATCH) && isset($MATCH[ 'columns' ], $MATCH[ 'keyword' ]))
+ {
+ $mode = '';
+
+ $mode_array = [
+ 'natural' => 'IN NATURAL LANGUAGE MODE',
+ 'natural+query' => 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION',
+ 'boolean' => 'IN BOOLEAN MODE',
+ 'query' => 'WITH QUERY EXPANSION'
+ ];
+
+ if (isset($MATCH[ 'mode' ], $mode_array[ $MATCH[ 'mode' ] ]))
+ {
+ $mode = ' ' . $mode_array[ $MATCH[ 'mode' ] ];
+ }
+
+ $columns = implode(', ', array_map([$this, 'columnQuote'], $MATCH[ 'columns' ]));
+ $map_key = $this->mapKey();
+ $map[ $map_key ] = [$MATCH[ 'keyword' ], PDO::PARAM_STR];
+
+ $where_clause .= ($where_clause !== '' ? ' AND ' : ' WHERE') . ' MATCH (' . $columns . ') AGAINST (' . $map_key . $mode . ')';
+ }
+ }
+
+ if (isset($where[ 'GROUP' ]))
+ {
+ $GROUP = $where[ 'GROUP' ];
+
+ if (is_array($GROUP))
+ {
+ $stack = [];
+
+ foreach ($GROUP as $column => $value)
+ {
+ $stack[] = $this->columnQuote($value);
+ }
+
+ $where_clause .= ' GROUP BY ' . implode(',', $stack);
+ }
+ elseif ($raw = $this->buildRaw($GROUP, $map))
+ {
+ $where_clause .= ' GROUP BY ' . $raw;
+ }
+ else
+ {
+ $where_clause .= ' GROUP BY ' . $this->columnQuote($GROUP);
+ }
+
+ if (isset($where[ 'HAVING' ]))
+ {
+ if ($raw = $this->buildRaw($where[ 'HAVING' ], $map))
+ {
+ $where_clause .= ' HAVING ' . $raw;
+ }
+ else
+ {
+ $where_clause .= ' HAVING ' . $this->dataImplode($where[ 'HAVING' ], $map, ' AND');
+ }
+ }
+ }
+
+ if (isset($where[ 'ORDER' ]))
+ {
+ $ORDER = $where[ 'ORDER' ];
+
+ if (is_array($ORDER))
+ {
+ $stack = [];
+
+ foreach ($ORDER as $column => $value)
+ {
+ if (is_array($value))
+ {
+ $stack[] = 'FIELD(' . $this->columnQuote($column) . ', ' . $this->arrayQuote($value) . ')';
+ }
+ elseif ($value === 'ASC' || $value === 'DESC')
+ {
+ $stack[] = $this->columnQuote($column) . ' ' . $value;
+ }
+ elseif (is_int($column))
+ {
+ $stack[] = $this->columnQuote($value);
+ }
+ }
+
+ $where_clause .= ' ORDER BY ' . implode(',', $stack);
+ }
+ elseif ($raw = $this->buildRaw($ORDER, $map))
+ {
+ $where_clause .= ' ORDER BY ' . $raw;
+ }
+ else
+ {
+ $where_clause .= ' ORDER BY ' . $this->columnQuote($ORDER);
+ }
+
+ if (
+ isset($where[ 'LIMIT' ]) &&
+ in_array($this->type, ['oracle', 'mssql'])
+ )
+ {
+ $LIMIT = $where[ 'LIMIT' ];
+
+ if (is_numeric($LIMIT))
+ {
+ $LIMIT = [0, $LIMIT];
+ }
+
+ if (
+ is_array($LIMIT) &&
+ is_numeric($LIMIT[ 0 ]) &&
+ is_numeric($LIMIT[ 1 ])
+ )
+ {
+ $where_clause .= ' OFFSET ' . $LIMIT[ 0 ] . ' ROWS FETCH NEXT ' . $LIMIT[ 1 ] . ' ROWS ONLY';
+ }
+ }
+ }
+
+ if (isset($where[ 'LIMIT' ]) && !in_array($this->type, ['oracle', 'mssql']))
+ {
+ $LIMIT = $where[ 'LIMIT' ];
+
+ if (is_numeric($LIMIT))
+ {
+ $where_clause .= ' LIMIT ' . $LIMIT;
+ }
+ elseif (
+ is_array($LIMIT) &&
+ is_numeric($LIMIT[ 0 ]) &&
+ is_numeric($LIMIT[ 1 ])
+ )
+ {
+ $where_clause .= ' LIMIT ' . $LIMIT[ 1 ] . ' OFFSET ' . $LIMIT[ 0 ];
+ }
+ }
+ }
+ elseif ($raw = $this->buildRaw($where, $map))
+ {
+ $where_clause .= ' ' . $raw;
+ }
+
+ return $where_clause;
+ }
+
+ protected function selectContext($table, &$map, $join, &$columns = null, $where = null, $column_fn = null)
+ {
+ preg_match('/(?[a-zA-Z0-9_]+)\s*\((?[a-zA-Z0-9_]+)\)/i', $table, $table_match);
+
+ if (isset($table_match[ 'table' ], $table_match[ 'alias' ]))
+ {
+ $table = $this->tableQuote($table_match[ 'table' ]);
+
+ $table_query = $table . ' AS ' . $this->tableQuote($table_match[ 'alias' ]);
+ }
+ else
+ {
+ $table = $this->tableQuote($table);
+
+ $table_query = $table;
+ }
+
+ $is_join = false;
+ $join_key = is_array($join) ? array_keys($join) : null;
+
+ if (
+ isset($join_key[ 0 ]) &&
+ strpos($join_key[ 0 ], '[') === 0
+ )
+ {
+ $is_join = true;
+ $table_query .= ' ' . $this->buildJoin($table, $join);
+ }
+ else
+ {
+ if (is_null($columns))
+ {
+ if (
+ !is_null($where) ||
+ (is_array($join) && isset($column_fn))
+ )
+ {
+ $where = $join;
+ $columns = null;
+ }
+ else
+ {
+ $where = null;
+ $columns = $join;
+ }
+ }
+ else
+ {
+ $where = $columns;
+ $columns = $join;
+ }
+ }
+
+ if (isset($column_fn))
+ {
+ if ($column_fn === 1)
+ {
+ $column = '1';
+
+ if (is_null($where))
+ {
+ $where = $columns;
+ }
+ }
+ elseif ($raw = $this->buildRaw($column_fn, $map))
+ {
+ $column = $raw;
+ }
+ else
+ {
+ if (empty($columns) || $this->isRaw($columns))
+ {
+ $columns = '*';
+ $where = $join;
+ }
+
+ $column = $column_fn . '(' . $this->columnPush($columns, $map, true) . ')';
+ }
+ }
+ else
+ {
+ $column = $this->columnPush($columns, $map, true, $is_join);
+ }
+
+ return 'SELECT ' . $column . ' FROM ' . $table_query . $this->whereClause($where, $map);
+ }
+
+ protected function buildJoin($table, $join)
+ {
+ $table_join = [];
+
+ $join_array = [
+ '>' => 'LEFT',
+ '<' => 'RIGHT',
+ '<>' => 'FULL',
+ '><' => 'INNER'
+ ];
+
+ foreach($join as $sub_table => $relation)
+ {
+ preg_match('/(\[(?\<\>?|\>\)\])?(?[a-zA-Z0-9_]+)\s?(\((?[a-zA-Z0-9_]+)\))?/', $sub_table, $match);
+
+ if ($match[ 'join' ] !== '' && $match[ 'table' ] !== '')
+ {
+ if (is_string($relation))
+ {
+ $relation = 'USING ("' . $relation . '")';
+ }
+
+ if (is_array($relation))
+ {
+ // For ['column1', 'column2']
+ if (isset($relation[ 0 ]))
+ {
+ $relation = 'USING ("' . implode('", "', $relation) . '")';
+ }
+ else
+ {
+ $joins = [];
+
+ foreach ($relation as $key => $value)
+ {
+ $joins[] = (
+ strpos($key, '.') > 0 ?
+ // For ['tableB.column' => 'column']
+ $this->columnQuote($key) :
+
+ // For ['column1' => 'column2']
+ $table . '."' . $key . '"'
+ ) .
+ ' = ' .
+ $this->tableQuote(isset($match[ 'alias' ]) ? $match[ 'alias' ] : $match[ 'table' ]) . '."' . $value . '"';
+ }
+
+ $relation = 'ON ' . implode(' AND ', $joins);
+ }
+ }
+
+ $table_name = $this->tableQuote($match[ 'table' ]) . ' ';
+
+ if (isset($match[ 'alias' ]))
+ {
+ $table_name .= 'AS ' . $this->tableQuote($match[ 'alias' ]) . ' ';
+ }
+
+ $table_join[] = $join_array[ $match[ 'join' ] ] . ' JOIN ' . $table_name . $relation;
+ }
+ }
+
+ return implode(' ', $table_join);
+ }
+
+ protected function columnMap($columns, &$stack, $root)
+ {
+ if ($columns === '*')
+ {
+ return $stack;
+ }
+
+ foreach ($columns as $key => $value)
+ {
+ if (is_int($key))
+ {
+ preg_match('/([a-zA-Z0-9_]+\.)?(?[a-zA-Z0-9_]+)(?:\s*\((?[a-zA-Z0-9_]+)\))?(?:\s*\[(?(?:String|Bool|Int|Number|Object|JSON))\])?/i', $value, $key_match);
+
+ $column_key = !empty($key_match[ 'alias' ]) ?
+ $key_match[ 'alias' ] :
+ $key_match[ 'column' ];
+
+ if (isset($key_match[ 'type' ]))
+ {
+ $stack[ $value ] = [$column_key, $key_match[ 'type' ]];
+ }
+ else
+ {
+ $stack[ $value ] = [$column_key, 'String'];
+ }
+ }
+ elseif ($this->isRaw($value))
+ {
+ preg_match('/([a-zA-Z0-9_]+\.)?(?[a-zA-Z0-9_]+)(\s*\[(?(String|Bool|Int|Number))\])?/i', $key, $key_match);
+
+ $column_key = $key_match[ 'column' ];
+
+ if (isset($key_match[ 'type' ]))
+ {
+ $stack[ $key ] = [$column_key, $key_match[ 'type' ]];
+ }
+ else
+ {
+ $stack[ $key ] = [$column_key, 'String'];
+ }
+ }
+ elseif (!is_int($key) && is_array($value))
+ {
+ if ($root && count(array_keys($columns)) === 1)
+ {
+ $stack[ $key ] = [$key, 'String'];
+ }
+
+ $this->columnMap($value, $stack, false);
+ }
+ }
+
+ return $stack;
+ }
+
+ protected function dataMap($data, $columns, $column_map, &$stack, $root, &$result)
+ {
+ if ($root)
+ {
+ $columns_key = array_keys($columns);
+
+ if (count($columns_key) === 1 && is_array($columns[$columns_key[0]]))
+ {
+ $index_key = array_keys($columns)[0];
+ $data_key = preg_replace("/^[a-zA-Z0-9_]+\./i", "", $index_key);
+
+ $current_stack = [];
+
+ foreach ($data as $item)
+ {
+ $this->dataMap($data, $columns[ $index_key ], $column_map, $current_stack, false, $result);
+
+ $index = $data[ $data_key ];
+
+ $result[ $index ] = $current_stack;
+ }
+ }
+ else
+ {
+ $current_stack = [];
+
+ $this->dataMap($data, $columns, $column_map, $current_stack, false, $result);
+
+ $result[] = $current_stack;
+ }
+
+ return;
+ }
+
+ foreach ($columns as $key => $value)
+ {
+ $isRaw = $this->isRaw($value);
+
+ if (is_int($key) || $isRaw)
+ {
+ $map = $column_map[ $isRaw ? $key : $value ];
+
+ $column_key = $map[ 0 ];
+
+ $item = $data[ $column_key ];
+
+ if (isset($map[ 1 ]))
+ {
+ if ($isRaw && in_array($map[ 1 ], ['Object', 'JSON']))
+ {
+ continue;
+ }
+
+ if (is_null($item))
+ {
+ $stack[ $column_key ] = null;
+ continue;
+ }
+
+ switch ($map[ 1 ])
+ {
+ case 'Number':
+ $stack[ $column_key ] = (double) $item;
+ break;
+
+ case 'Int':
+ $stack[ $column_key ] = (int) $item;
+ break;
+
+ case 'Bool':
+ $stack[ $column_key ] = (bool) $item;
+ break;
+
+ case 'Object':
+ $stack[ $column_key ] = unserialize($item);
+ break;
+
+ case 'JSON':
+ $stack[ $column_key ] = json_decode($item, true);
+ break;
+
+ case 'String':
+ $stack[ $column_key ] = $item;
+ break;
+ }
+ }
+ else
+ {
+ $stack[ $column_key ] = $item;
+ }
+ }
+ else
+ {
+ $current_stack = [];
+
+ $this->dataMap($data, $value, $column_map, $current_stack, false, $result);
+
+ $stack[ $key ] = $current_stack;
+ }
+ }
+ }
+
+ public function create($table, $columns, $options = null)
+ {
+ $stack = [];
+
+ $tableName = $this->prefix . $table;
+
+ foreach ($columns as $name => $definition)
+ {
+ if (is_int($name))
+ {
+ $stack[] = preg_replace('/\<([a-zA-Z0-9_]+)\>/i', '"$1"', $definition);
+ }
+ elseif (is_array($definition))
+ {
+ $stack[] = $name . ' ' . implode(' ', $definition);
+ }
+ elseif (is_string($definition))
+ {
+ $stack[] = $name . ' ' . $this->query($definition);
+ }
+ }
+
+ $table_option = '';
+
+ if (is_array($options))
+ {
+ $option_stack = [];
+
+ foreach ($options as $key => $value)
+ {
+ if (is_string($value) || is_int($value))
+ {
+ $option_stack[] = "$key = $value";
+ }
+ }
+
+ $table_option = ' ' . implode(', ', $option_stack);
+ }
+ elseif (is_string($options))
+ {
+ $table_option = ' ' . $options;
+ }
+
+ return $this->exec("CREATE TABLE IF NOT EXISTS $tableName (" . implode(', ', $stack) . ")$table_option");
+ }
+
+ public function drop($table)
+ {
+ $tableName = $this->prefix . $table;
+
+ return $this->exec("DROP TABLE IF EXISTS $tableName");
+ }
+
+ public function select($table, $join, $columns = null, $where = null)
+ {
+ $map = [];
+ $result = [];
+ $column_map = [];
+
+ $index = 0;
+
+ $column = $where === null ? $join : $columns;
+
+ $is_single = (is_string($column) && $column !== '*');
+
+ $query = $this->exec($this->selectContext($table, $map, $join, $columns, $where), $map);
+
+ $this->columnMap($columns, $column_map, true);
+
+ if (!$this->statement)
+ {
+ return false;
+ }
+
+ if ($columns === '*')
+ {
+ return $query->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ while ($data = $query->fetch(PDO::FETCH_ASSOC))
+ {
+ $current_stack = [];
+
+ $this->dataMap($data, $columns, $column_map, $current_stack, true, $result);
+ }
+
+ if ($is_single)
+ {
+ $single_result = [];
+ $result_key = $column_map[ $column ][ 0 ];
+
+ foreach ($result as $item)
+ {
+ $single_result[] = $item[ $result_key ];
+ }
+
+ return $single_result;
+ }
+
+ return $result;
+ }
+
+ public function insert($table, $datas)
+ {
+ $stack = [];
+ $columns = [];
+ $fields = [];
+ $map = [];
+
+ if (!isset($datas[ 0 ]))
+ {
+ $datas = [$datas];
+ }
+
+ foreach ($datas as $data)
+ {
+ foreach ($data as $key => $value)
+ {
+ $columns[] = $key;
+ }
+ }
+
+ $columns = array_unique($columns);
+
+ foreach ($datas as $data)
+ {
+ $values = [];
+
+ foreach ($columns as $key)
+ {
+ if ($raw = $this->buildRaw($data[ $key ], $map))
+ {
+ $values[] = $raw;
+ continue;
+ }
+
+ $map_key = $this->mapKey();
+
+ $values[] = $map_key;
+
+ if (!isset($data[ $key ]))
+ {
+ $map[ $map_key ] = [null, PDO::PARAM_NULL];
+ }
+ else
+ {
+ $value = $data[ $key ];
+
+ $type = gettype($value);
+
+ switch ($type)
+ {
+ case 'array':
+ $map[ $map_key ] = [
+ strpos($key, '[JSON]') === strlen($key) - 6 ?
+ json_encode($value) :
+ serialize($value),
+ PDO::PARAM_STR
+ ];
+ break;
+
+ case 'object':
+ $value = serialize($value);
+
+ case 'NULL':
+ case 'resource':
+ case 'boolean':
+ case 'integer':
+ case 'double':
+ case 'string':
+ $map[ $map_key ] = $this->typeMap($value, $type);
+ break;
+ }
+ }
+ }
+
+ $stack[] = '(' . implode(', ', $values) . ')';
+ }
+
+ foreach ($columns as $key)
+ {
+ $fields[] = $this->columnQuote(preg_replace("/(\s*\[JSON\]$)/i", '', $key));
+ }
+
+ return $this->exec('INSERT INTO ' . $this->tableQuote($table) . ' (' . implode(', ', $fields) . ') VALUES ' . implode(', ', $stack), $map);
+ }
+
+ public function update($table, $data, $where = null)
+ {
+ $fields = [];
+ $map = [];
+
+ foreach ($data as $key => $value)
+ {
+ $column = $this->columnQuote(preg_replace("/(\s*\[(JSON|\+|\-|\*|\/)\]$)/i", '', $key));
+
+ if ($raw = $this->buildRaw($value, $map))
+ {
+ $fields[] = $column . ' = ' . $raw;
+ continue;
+ }
+
+ $map_key = $this->mapKey();
+
+ preg_match('/(?[a-zA-Z0-9_]+)(\[(?\+|\-|\*|\/)\])?/i', $key, $match);
+
+ if (isset($match[ 'operator' ]))
+ {
+ if (is_numeric($value))
+ {
+ $fields[] = $column . ' = ' . $column . ' ' . $match[ 'operator' ] . ' ' . $value;
+ }
+ }
+ else
+ {
+ $fields[] = $column . ' = ' . $map_key;
+
+ $type = gettype($value);
+
+ switch ($type)
+ {
+ case 'array':
+ $map[ $map_key ] = [
+ strpos($key, '[JSON]') === strlen($key) - 6 ?
+ json_encode($value) :
+ serialize($value),
+ PDO::PARAM_STR
+ ];
+ break;
+
+ case 'object':
+ $value = serialize($value);
+
+ case 'NULL':
+ case 'resource':
+ case 'boolean':
+ case 'integer':
+ case 'double':
+ case 'string':
+ $map[ $map_key ] = $this->typeMap($value, $type);
+ break;
+ }
+ }
+ }
+
+ return $this->exec('UPDATE ' . $this->tableQuote($table) . ' SET ' . implode(', ', $fields) . $this->whereClause($where, $map), $map);
+ }
+
+ public function delete($table, $where)
+ {
+ $map = [];
+
+ return $this->exec('DELETE FROM ' . $this->tableQuote($table) . $this->whereClause($where, $map), $map);
+ }
+
+ public function replace($table, $columns, $where = null)
+ {
+ if (!is_array($columns) || empty($columns))
+ {
+ return false;
+ }
+
+ $map = [];
+ $stack = [];
+
+ foreach ($columns as $column => $replacements)
+ {
+ if (is_array($replacements))
+ {
+ foreach ($replacements as $old => $new)
+ {
+ $map_key = $this->mapKey();
+
+ $stack[] = $this->columnQuote($column) . ' = REPLACE(' . $this->columnQuote($column) . ', ' . $map_key . 'a, ' . $map_key . 'b)';
+
+ $map[ $map_key . 'a' ] = [$old, PDO::PARAM_STR];
+ $map[ $map_key . 'b' ] = [$new, PDO::PARAM_STR];
+ }
+ }
+ }
+
+ if (!empty($stack))
+ {
+ return $this->exec('UPDATE ' . $this->tableQuote($table) . ' SET ' . implode(', ', $stack) . $this->whereClause($where, $map), $map);
+ }
+
+ return false;
+ }
+
+ public function get($table, $join = null, $columns = null, $where = null)
+ {
+ $map = [];
+ $result = [];
+ $column_map = [];
+ $current_stack = [];
+
+ if ($where === null)
+ {
+ $column = $join;
+ unset($columns[ 'LIMIT' ]);
+ }
+ else
+ {
+ $column = $columns;
+ unset($where[ 'LIMIT' ]);
+ }
+
+ $is_single = (is_string($column) && $column !== '*');
+
+ $query = $this->exec($this->selectContext($table, $map, $join, $columns, $where) . ' LIMIT 1', $map);
+
+ if (!$this->statement)
+ {
+ return false;
+ }
+
+ $data = $query->fetchAll(PDO::FETCH_ASSOC);
+
+ if (isset($data[ 0 ]))
+ {
+ if ($column === '*')
+ {
+ return $data[ 0 ];
+ }
+
+ $this->columnMap($columns, $column_map, true);
+
+ $this->dataMap($data[ 0 ], $columns, $column_map, $current_stack, true, $result);
+
+ if ($is_single)
+ {
+ return $result[ 0 ][ $column_map[ $column ][ 0 ] ];
+ }
+
+ return $result[ 0 ];
+ }
+ }
+
+ public function has($table, $join, $where = null)
+ {
+ $map = [];
+ $column = null;
+
+ if ($this->type === 'mssql')
+ {
+ $query = $this->exec($this->selectContext($table, $map, $join, $column, $where, Medoo::raw('TOP 1 1')), $map);
+ }
+ else
+ {
+ $query = $this->exec('SELECT EXISTS(' . $this->selectContext($table, $map, $join, $column, $where, 1) . ')', $map);
+ }
+
+ if (!$this->statement)
+ {
+ return false;
+ }
+
+ $result = $query->fetchColumn();
+
+ return $result === '1' || $result === 1 || $result === true;
+ }
+
+ public function rand($table, $join = null, $columns = null, $where = null)
+ {
+ $type = $this->type;
+
+ $order = 'RANDOM()';
+
+ if ($type === 'mysql')
+ {
+ $order = 'RAND()';
+ }
+ elseif ($type === 'mssql')
+ {
+ $order = 'NEWID()';
+ }
+
+ $order_raw = $this->raw($order);
+
+ if ($where === null)
+ {
+ if ($columns === null)
+ {
+ $columns = [
+ 'ORDER' => $order_raw
+ ];
+ }
+ else
+ {
+ $column = $join;
+ unset($columns[ 'ORDER' ]);
+
+ $columns[ 'ORDER' ] = $order_raw;
+ }
+ }
+ else
+ {
+ unset($where[ 'ORDER' ]);
+
+ $where[ 'ORDER' ] = $order_raw;
+ }
+
+ return $this->select($table, $join, $columns, $where);
+ }
+
+ private function aggregate($type, $table, $join = null, $column = null, $where = null)
+ {
+ $map = [];
+
+ $query = $this->exec($this->selectContext($table, $map, $join, $column, $where, strtoupper($type)), $map);
+
+ if (!$this->statement)
+ {
+ return false;
+ }
+
+ $number = $query->fetchColumn();
+
+ return is_numeric($number) ? $number + 0 : $number;
+ }
+
+ public function count($table, $join = null, $column = null, $where = null)
+ {
+ return $this->aggregate('count', $table, $join, $column, $where);
+ }
+
+ public function avg($table, $join, $column = null, $where = null)
+ {
+ return $this->aggregate('avg', $table, $join, $column, $where);
+ }
+
+ public function max($table, $join, $column = null, $where = null)
+ {
+ return $this->aggregate('max', $table, $join, $column, $where);
+ }
+
+ public function min($table, $join, $column = null, $where = null)
+ {
+ return $this->aggregate('min', $table, $join, $column, $where);
+ }
+
+ public function sum($table, $join, $column = null, $where = null)
+ {
+ return $this->aggregate('sum', $table, $join, $column, $where);
+ }
+
+ public function action($actions)
+ {
+ if (is_callable($actions))
+ {
+ $this->pdo->beginTransaction();
+
+ try {
+ $result = $actions($this);
+
+ if ($result === false)
+ {
+ $this->pdo->rollBack();
+ }
+ else
+ {
+ $this->pdo->commit();
+ }
+ }
+ catch (Exception $e) {
+ $this->pdo->rollBack();
+
+ throw $e;
+ }
+
+ return $result;
+ }
+
+ return false;
+ }
+
+ public function id()
+ {
+ if ($this->statement == null)
+ {
+ return null;
+ }
+
+ $type = $this->type;
+
+ if ($type === 'oracle')
+ {
+ return 0;
+ }
+ elseif ($type === 'pgsql')
+ {
+ return $this->pdo->query('SELECT LASTVAL()')->fetchColumn();
+ }
+
+ $lastId = $this->pdo->lastInsertId();
+
+ if ($lastId != "0" && $lastId != "")
+ {
+ return $lastId;
+ }
+
+ return null;
+ }
+
+ public function debug()
+ {
+ $this->debug_mode = true;
+
+ return $this;
+ }
+
+ public function error()
+ {
+ return $this->errorInfo;
+ }
+
+ public function last()
+ {
+ $log = end($this->logs);
+
+ return $this->generate($log[ 0 ], $log[ 1 ]);
+ }
+
+ public function log()
+ {
+ return array_map(function ($log)
+ {
+ return $this->generate($log[ 0 ], $log[ 1 ]);
+ },
+ $this->logs
+ );
+ }
+
+ public function info()
+ {
+ $output = [
+ 'server' => 'SERVER_INFO',
+ 'driver' => 'DRIVER_NAME',
+ 'client' => 'CLIENT_VERSION',
+ 'version' => 'SERVER_VERSION',
+ 'connection' => 'CONNECTION_STATUS'
+ ];
+
+ foreach ($output as $key => $value)
+ {
+ $output[ $key ] = @$this->pdo->getAttribute(constant('PDO::ATTR_' . $value));
+ }
+
+ $output[ 'dsn' ] = $this->dsn;
+
+ return $output;
+ }
+}
\ No newline at end of file
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-af.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-af.php
new file mode 100644
index 0000000..0b2a72d
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-af.php
@@ -0,0 +1,26 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'خطأ SMTP : لا يمكن تأكيد الهوية.';
+$PHPMAILER_LANG['connect_host'] = 'خطأ SMTP: لا يمكن الاتصال بالخادم SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'خطأ SMTP: لم يتم قبول المعلومات .';
+$PHPMAILER_LANG['empty_message'] = 'نص الرسالة فارغ';
+$PHPMAILER_LANG['encoding'] = 'ترميز غير معروف: ';
+$PHPMAILER_LANG['execute'] = 'لا يمكن تنفيذ : ';
+$PHPMAILER_LANG['file_access'] = 'لا يمكن الوصول للملف: ';
+$PHPMAILER_LANG['file_open'] = 'خطأ في الملف: لا يمكن فتحه: ';
+$PHPMAILER_LANG['from_failed'] = 'خطأ على مستوى عنوان المرسل : ';
+$PHPMAILER_LANG['instantiate'] = 'لا يمكن توفير خدمة البريد.';
+$PHPMAILER_LANG['invalid_address'] = 'الإرسال غير ممكن لأن عنوان البريد الإلكتروني غير صالح: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' برنامج الإرسال غير مدعوم.';
+$PHPMAILER_LANG['provide_address'] = 'يجب توفير عنوان البريد الإلكتروني لمستلم واحد على الأقل.';
+$PHPMAILER_LANG['recipients_failed'] = 'خطأ SMTP: الأخطاء التالية فشل في الارسال لكل من : ';
+$PHPMAILER_LANG['signing'] = 'خطأ في التوقيع: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() غير ممكن.';
+$PHPMAILER_LANG['smtp_error'] = 'خطأ على مستوى الخادم SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'لا يمكن تعيين أو إعادة تعيين متغير: ';
+$PHPMAILER_LANG['extension_missing'] = 'الإضافة غير موجودة: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-az.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-az.php
new file mode 100644
index 0000000..552167e
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-az.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP Greška: Neuspjela prijava.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Greška: Nije moguće spojiti se sa SMTP serverom.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Greška: Podatci nisu prihvaćeni.';
+$PHPMAILER_LANG['empty_message'] = 'Sadržaj poruke je prazan.';
+$PHPMAILER_LANG['encoding'] = 'Nepoznata kriptografija: ';
+$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 navedenih e-mail adresa nije uspjelo: ';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Greška: Slanje na navedene e-mail adrese nije uspjelo: ';
+$PHPMAILER_LANG['instantiate'] = 'Ne mogu pokrenuti mail funkcionalnost.';
+$PHPMAILER_LANG['invalid_address'] = 'E-mail nije poslan. Neispravna e-mail adresa: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer nije podržan.';
+$PHPMAILER_LANG['provide_address'] = 'Definišite barem jednu adresu primaoca.';
+$PHPMAILER_LANG['signing'] = 'Greška prilikom prijave: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Spajanje na SMTP server nije uspjelo.';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP greška: ';
+$PHPMAILER_LANG['variable_set'] = 'Nije moguće postaviti varijablu ili je vratiti nazad: ';
+$PHPMAILER_LANG['extension_missing'] = 'Nedostaje ekstenzija: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-be.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-be.php
new file mode 100644
index 0000000..9e92dda
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-be.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Памылка SMTP: памылка ідэнтыфікацыі.';
+$PHPMAILER_LANG['connect_host'] = 'Памылка SMTP: нельга ўстанавіць сувязь з SMTP-серверам.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Памылка SMTP: звесткі непрынятыя.';
+$PHPMAILER_LANG['empty_message'] = 'Пустое паведамленне.';
+$PHPMAILER_LANG['encoding'] = 'Невядомая кадыроўка тэксту: ';
+$PHPMAILER_LANG['execute'] = 'Нельга выканаць каманду: ';
+$PHPMAILER_LANG['file_access'] = 'Няма доступу да файла: ';
+$PHPMAILER_LANG['file_open'] = 'Нельга адкрыць файл: ';
+$PHPMAILER_LANG['from_failed'] = 'Няправільны адрас адпраўніка: ';
+$PHPMAILER_LANG['instantiate'] = 'Нельга прымяніць функцыю mail().';
+$PHPMAILER_LANG['invalid_address'] = 'Нельга даслаць паведамленне, няправільны email атрымальніка: ';
+$PHPMAILER_LANG['provide_address'] = 'Запоўніце, калі ласка, правільны email атрымальніка.';
+$PHPMAILER_LANG['mailer_not_supported'] = ' - паштовы сервер не падтрымліваецца.';
+$PHPMAILER_LANG['recipients_failed'] = 'Памылка SMTP: няправільныя атрымальнікі: ';
+$PHPMAILER_LANG['signing'] = 'Памылка подпісу паведамлення: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Памылка сувязі з SMTP-серверам.';
+$PHPMAILER_LANG['smtp_error'] = 'Памылка SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Нельга ўстанавіць або перамяніць значэнне пераменнай: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-bg.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-bg.php
new file mode 100644
index 0000000..c41f675
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-bg.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP грешка: Не може да се удостовери пред сървъра.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP грешка: Не може да се свърже с SMTP хоста.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP грешка: данните не са приети.';
+$PHPMAILER_LANG['empty_message'] = 'Съдържанието на съобщението е празно';
+$PHPMAILER_LANG['encoding'] = 'Неизвестно кодиране: ';
+$PHPMAILER_LANG['execute'] = 'Не може да се изпълни: ';
+$PHPMAILER_LANG['file_access'] = 'Няма достъп до файл: ';
+$PHPMAILER_LANG['file_open'] = 'Файлова грешка: Не може да се отвори файл: ';
+$PHPMAILER_LANG['from_failed'] = 'Следните адреси за подател са невалидни: ';
+$PHPMAILER_LANG['instantiate'] = 'Не може да се инстанцира функцията mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Невалиден адрес: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' - пощенски сървър не се поддържа.';
+$PHPMAILER_LANG['provide_address'] = 'Трябва да предоставите поне един email адрес за получател.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP грешка: Следните адреси за Получател са невалидни: ';
+$PHPMAILER_LANG['signing'] = 'Грешка при подписване: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP провален connect().';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP сървърна грешка: ';
+$PHPMAILER_LANG['variable_set'] = 'Не може да се установи или възстанови променлива: ';
+$PHPMAILER_LANG['extension_missing'] = 'Липсва разширение: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ca.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ca.php
new file mode 100644
index 0000000..3468485
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ca.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Error SMTP: No s’ha pogut autenticar.';
+$PHPMAILER_LANG['connect_host'] = 'Error SMTP: No es pot connectar al servidor SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Dades no acceptades.';
+$PHPMAILER_LANG['empty_message'] = 'El cos del missatge està buit.';
+$PHPMAILER_LANG['encoding'] = 'Codificació desconeguda: ';
+$PHPMAILER_LANG['execute'] = 'No es pot executar: ';
+$PHPMAILER_LANG['file_access'] = 'No es pot accedir a l’arxiu: ';
+$PHPMAILER_LANG['file_open'] = 'Error d’Arxiu: No es pot obrir l’arxiu: ';
+$PHPMAILER_LANG['from_failed'] = 'La(s) següent(s) adreces de remitent han fallat: ';
+$PHPMAILER_LANG['instantiate'] = 'No s’ha pogut crear una instància de la funció Mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Adreça d’email invalida: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer no està suportat';
+$PHPMAILER_LANG['provide_address'] = 'S’ha de proveir almenys una adreça d’email com a destinatari.';
+$PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Els següents destinataris han fallat: ';
+$PHPMAILER_LANG['signing'] = 'Error al signar: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Ha fallat el SMTP Connect().';
+$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'No s’ha pogut establir o restablir la variable: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ch.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ch.php
new file mode 100644
index 0000000..500c952
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ch.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP 错误:身份验证失败。';
+$PHPMAILER_LANG['connect_host'] = 'SMTP 错误: 不能连接SMTP主机。';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP 错误: 数据不可接受。';
+//$PHPMAILER_LANG['empty_message'] = 'Message body empty';
+$PHPMAILER_LANG['encoding'] = '未知编码:';
+$PHPMAILER_LANG['execute'] = '不能执行: ';
+$PHPMAILER_LANG['file_access'] = '不能访问文件:';
+$PHPMAILER_LANG['file_open'] = '文件错误:不能打开文件:';
+$PHPMAILER_LANG['from_failed'] = '下面的发送地址邮件发送失败了: ';
+$PHPMAILER_LANG['instantiate'] = '不能实现mail方法。';
+//$PHPMAILER_LANG['invalid_address'] = 'Invalid address: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' 您所选择的发送邮件的方法并不支持。';
+$PHPMAILER_LANG['provide_address'] = '您必须提供至少一个 收信人的email地址。';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误: 下面的 收件人失败了: ';
+//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
+//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
+//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
+//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-cs.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-cs.php
new file mode 100644
index 0000000..e770a1a
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-cs.php
@@ -0,0 +1,28 @@
+
+ * Rewrite and extension of the work by Mikael Stokkebro
+ *
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP fejl: Login mislykkedes.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP fejl: Forbindelse til SMTP serveren kunne ikke oprettes.';
+$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['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['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['signing'] = 'Signeringsfejl: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fejlede.';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: ';
+$PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: ';
+$PHPMAILER_LANG['extension_missing'] = 'Udvidelse mangler: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-de.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-de.php
new file mode 100644
index 0000000..e7e59d2
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-de.php
@@ -0,0 +1,28 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.';
+$PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.';
+$PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.';
+$PHPMAILER_LANG['encoding'] = 'Codificación desconocida: ';
+$PHPMAILER_LANG['execute'] = 'Imposible ejecutar: ';
+$PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: ';
+$PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: ';
+$PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: ';
+$PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer no está soportado.';
+$PHPMAILER_LANG['provide_address'] = 'Debe proporcionar al menos una dirección de email de destino.';
+$PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinos fallaron: ';
+$PHPMAILER_LANG['signing'] = 'Error al firmar: ';
+$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: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-et.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-et.php
new file mode 100644
index 0000000..93addc9
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-et.php
@@ -0,0 +1,28 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP Viga: Autoriseerimise viga.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Viga: Ei õnnestunud luua ühendust SMTP serveriga.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Viga: Vigased andmed.';
+$PHPMAILER_LANG['empty_message'] = 'Tühi kirja sisu';
+$PHPMAILER_LANG["encoding"] = 'Tundmatu kodeering: ';
+$PHPMAILER_LANG['execute'] = 'Tegevus ebaõnnestus: ';
+$PHPMAILER_LANG['file_access'] = 'Pole piisavalt õiguseid järgneva faili avamiseks: ';
+$PHPMAILER_LANG['file_open'] = 'Faili Viga: Faili avamine ebaõnnestus: ';
+$PHPMAILER_LANG['from_failed'] = 'Järgnev saatja e-posti aadress on vigane: ';
+$PHPMAILER_LANG['instantiate'] = 'mail funktiooni käivitamine ebaõnnestus.';
+$PHPMAILER_LANG['invalid_address'] = 'Saatmine peatatud, e-posti address vigane: ';
+$PHPMAILER_LANG['provide_address'] = 'Te peate määrama vähemalt ühe saaja e-posti aadressi.';
+$PHPMAILER_LANG['mailer_not_supported'] = ' maileri tugi puudub.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Viga: Järgnevate saajate e-posti aadressid on vigased: ';
+$PHPMAILER_LANG["signing"] = 'Viga allkirjastamisel: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() ebaõnnestus.';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP serveri viga: ';
+$PHPMAILER_LANG['variable_set'] = 'Ei õnnestunud määrata või lähtestada muutujat: ';
+$PHPMAILER_LANG['extension_missing'] = 'Nõutud laiendus on puudu: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fa.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fa.php
new file mode 100644
index 0000000..295a47f
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fa.php
@@ -0,0 +1,28 @@
+
+ * @author Mohammad Hossein Mojtahedi
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'خطای SMTP: احراز هویت با شکست مواجه شد.';
+$PHPMAILER_LANG['connect_host'] = 'خطای SMTP: اتصال به سرور SMTP برقرار نشد.';
+$PHPMAILER_LANG['data_not_accepted'] = 'خطای SMTP: دادهها نادرست هستند.';
+$PHPMAILER_LANG['empty_message'] = 'بخش متن پیام خالی است.';
+$PHPMAILER_LANG['encoding'] = 'کدگذاری ناشناخته: ';
+$PHPMAILER_LANG['execute'] = 'امکان اجرا وجود ندارد: ';
+$PHPMAILER_LANG['file_access'] = 'امکان دسترسی به فایل وجود ندارد: ';
+$PHPMAILER_LANG['file_open'] = 'خطای File: امکان بازکردن فایل وجود ندارد: ';
+$PHPMAILER_LANG['from_failed'] = 'آدرس فرستنده اشتباه است: ';
+$PHPMAILER_LANG['instantiate'] = 'امکان معرفی تابع ایمیل وجود ندارد.';
+$PHPMAILER_LANG['invalid_address'] = 'آدرس ایمیل معتبر نیست: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer پشتیبانی نمیشود.';
+$PHPMAILER_LANG['provide_address'] = 'باید حداقل یک آدرس گیرنده وارد کنید.';
+$PHPMAILER_LANG['recipients_failed'] = 'خطای SMTP: ارسال به آدرس گیرنده با خطا مواجه شد: ';
+$PHPMAILER_LANG['signing'] = 'خطا در امضا: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'خطا در اتصال به SMTP.';
+$PHPMAILER_LANG['smtp_error'] = 'خطا در SMTP Server: ';
+$PHPMAILER_LANG['variable_set'] = 'امکان ارسال یا ارسال مجدد متغیرها وجود ندارد: ';
+$PHPMAILER_LANG['extension_missing'] = 'افزونه موجود نیست: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fi.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fi.php
new file mode 100644
index 0000000..243c054
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fi.php
@@ -0,0 +1,28 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP feilur: Kundi ikki góðkenna.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP feilur: Kundi ikki knýta samband við SMTP vert.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP feilur: Data ikki góðkent.';
+//$PHPMAILER_LANG['empty_message'] = 'Message body empty';
+$PHPMAILER_LANG['encoding'] = 'Ókend encoding: ';
+$PHPMAILER_LANG['execute'] = 'Kundi ikki útføra: ';
+$PHPMAILER_LANG['file_access'] = 'Kundi ikki tilganga fílu: ';
+$PHPMAILER_LANG['file_open'] = 'Fílu feilur: Kundi ikki opna fílu: ';
+$PHPMAILER_LANG['from_failed'] = 'fylgjandi Frá/From adressa miseydnaðist: ';
+$PHPMAILER_LANG['instantiate'] = 'Kuni ikki instantiera mail funktión.';
+//$PHPMAILER_LANG['invalid_address'] = 'Invalid address: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' er ikki supporterað.';
+$PHPMAILER_LANG['provide_address'] = 'Tú skal uppgeva minst móttakara-emailadressu(r).';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Feilur: Fylgjandi móttakarar miseydnaðust: ';
+//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
+//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
+//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
+//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fr.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fr.php
new file mode 100644
index 0000000..38a7a8e
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-fr.php
@@ -0,0 +1,38 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Erro SMTP: Non puido ser autentificado.';
+$PHPMAILER_LANG['connect_host'] = 'Erro SMTP: Non puido conectar co servidor SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Erro SMTP: Datos non aceptados.';
+$PHPMAILER_LANG['empty_message'] = 'Corpo da mensaxe vacía';
+$PHPMAILER_LANG['encoding'] = 'Codificación descoñecida: ';
+$PHPMAILER_LANG['execute'] = 'Non puido ser executado: ';
+$PHPMAILER_LANG['file_access'] = 'Nob puido acceder ó arquivo: ';
+$PHPMAILER_LANG['file_open'] = 'Erro de Arquivo: No puido abrir o arquivo: ';
+$PHPMAILER_LANG['from_failed'] = 'A(s) seguinte(s) dirección(s) de remitente(s) deron erro: ';
+$PHPMAILER_LANG['instantiate'] = 'Non puido crear unha instancia da función Mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Non puido envia-lo correo: dirección de email inválida: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer non está soportado.';
+$PHPMAILER_LANG['provide_address'] = 'Debe engadir polo menos unha dirección de email coma destino.';
+$PHPMAILER_LANG['recipients_failed'] = 'Erro SMTP: Os seguintes destinos fallaron: ';
+$PHPMAILER_LANG['signing'] = 'Erro ó firmar: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fallou.';
+$PHPMAILER_LANG['smtp_error'] = 'Erro do servidor SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Non puidemos axustar ou reaxustar a variábel: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-he.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-he.php
new file mode 100644
index 0000000..b123aa5
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-he.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'שגיאת SMTP: פעולת האימות נכשלה.';
+$PHPMAILER_LANG['connect_host'] = 'שגיאת SMTP: לא הצלחתי להתחבר לשרת SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'שגיאת SMTP: מידע לא התקבל.';
+$PHPMAILER_LANG['empty_message'] = 'גוף ההודעה ריק';
+$PHPMAILER_LANG['invalid_address'] = 'כתובת שגויה: ';
+$PHPMAILER_LANG['encoding'] = 'קידוד לא מוכר: ';
+$PHPMAILER_LANG['execute'] = 'לא הצלחתי להפעיל את: ';
+$PHPMAILER_LANG['file_access'] = 'לא ניתן לגשת לקובץ: ';
+$PHPMAILER_LANG['file_open'] = 'שגיאת קובץ: לא ניתן לגשת לקובץ: ';
+$PHPMAILER_LANG['from_failed'] = 'כתובות הנמענים הבאות נכשלו: ';
+$PHPMAILER_LANG['instantiate'] = 'לא הצלחתי להפעיל את פונקציית המייל.';
+$PHPMAILER_LANG['mailer_not_supported'] = ' אינה נתמכת.';
+$PHPMAILER_LANG['provide_address'] = 'חובה לספק לפחות כתובת אחת של מקבל המייל.';
+$PHPMAILER_LANG['recipients_failed'] = 'שגיאת SMTP: הנמענים הבאים נכשלו: ';
+$PHPMAILER_LANG['signing'] = 'שגיאת חתימה: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
+$PHPMAILER_LANG['smtp_error'] = 'שגיאת שרת SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'לא ניתן לקבוע או לשנות את המשתנה: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hi.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hi.php
new file mode 100644
index 0000000..d973a35
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hi.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP त्रुटि: प्रामाणिकता की जांच नहीं हो सका। ';
+$PHPMAILER_LANG['connect_host'] = 'SMTP त्रुटि: SMTP सर्वर से कनेक्ट नहीं हो सका। ';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP त्रुटि: डेटा स्वीकार नहीं किया जाता है। ';
+$PHPMAILER_LANG['empty_message'] = 'संदेश खाली है। ';
+$PHPMAILER_LANG['encoding'] = 'अज्ञात एन्कोडिंग प्रकार। ';
+$PHPMAILER_LANG['execute'] = 'आदेश को निष्पादित करने में विफल। ';
+$PHPMAILER_LANG['file_access'] = 'फ़ाइल उपलब्ध नहीं है। ';
+$PHPMAILER_LANG['file_open'] = 'फ़ाइल त्रुटि: फाइल को खोला नहीं जा सका। ';
+$PHPMAILER_LANG['from_failed'] = 'प्रेषक का पता गलत है। ';
+$PHPMAILER_LANG['instantiate'] = 'मेल फ़ंक्शन कॉल नहीं कर सकता है।';
+$PHPMAILER_LANG['invalid_address'] = 'पता गलत है। ';
+$PHPMAILER_LANG['mailer_not_supported'] = 'मेल सर्वर के साथ काम नहीं करता है। ';
+$PHPMAILER_LANG['provide_address'] = 'आपको कम से कम एक प्राप्तकर्ता का ई-मेल पता प्रदान करना होगा।';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP त्रुटि: निम्न प्राप्तकर्ताओं को पते भेजने में विफल। ';
+$PHPMAILER_LANG['signing'] = 'साइनअप त्रुटि:। ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP का connect () फ़ंक्शन विफल हुआ। ';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP सर्वर त्रुटि। ';
+$PHPMAILER_LANG['variable_set'] = 'चर को बना या संशोधित नहीं किया जा सकता। ';
+$PHPMAILER_LANG['extension_missing'] = 'एक्सटेन्षन गायब है: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hr.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hr.php
new file mode 100644
index 0000000..cacb6c3
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hr.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP Greška: Neuspjela autentikacija.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Greška: Ne mogu se spojiti na SMTP poslužitelj.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Greška: Podatci nisu prihvaćeni.';
+$PHPMAILER_LANG['empty_message'] = 'Sadržaj poruke je prazan.';
+$PHPMAILER_LANG['encoding'] = 'Nepoznati encoding: ';
+$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 s navedenih e-mail adresa nije uspjelo: ';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Greška: Slanje na navedenih e-mail adresa nije uspjelo: ';
+$PHPMAILER_LANG['instantiate'] = 'Ne mogu pokrenuti mail funkcionalnost.';
+$PHPMAILER_LANG['invalid_address'] = 'E-mail nije poslan. Neispravna e-mail adresa: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer nije podržan.';
+$PHPMAILER_LANG['provide_address'] = 'Definirajte barem jednu adresu primatelja.';
+$PHPMAILER_LANG['signing'] = 'Greška prilikom prijave: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Spajanje na SMTP poslužitelj nije uspjelo.';
+$PHPMAILER_LANG['smtp_error'] = 'Greška SMTP poslužitelja: ';
+$PHPMAILER_LANG['variable_set'] = 'Ne mogu postaviti varijablu niti ju vratiti nazad: ';
+$PHPMAILER_LANG['extension_missing'] = 'Nedostaje proširenje: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hu.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hu.php
new file mode 100644
index 0000000..e6b58b0
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-hu.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP -ի սխալ: չհաջողվեց ստուգել իսկությունը.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP -ի սխալ: չհաջողվեց կապ հաստատել SMTP սերվերի հետ.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP -ի սխալ: տվյալները ընդունված չեն.';
+$PHPMAILER_LANG['empty_message'] = 'Հաղորդագրությունը դատարկ է';
+$PHPMAILER_LANG['encoding'] = 'Կոդավորման անհայտ տեսակ: ';
+$PHPMAILER_LANG['execute'] = 'Չհաջողվեց իրականացնել հրամանը: ';
+$PHPMAILER_LANG['file_access'] = 'Ֆայլը հասանելի չէ: ';
+$PHPMAILER_LANG['file_open'] = 'Ֆայլի սխալ: ֆայլը չհաջողվեց բացել: ';
+$PHPMAILER_LANG['from_failed'] = 'Ուղարկողի հետևյալ հասցեն սխալ է: ';
+$PHPMAILER_LANG['instantiate'] = 'Հնարավոր չէ կանչել mail ֆունկցիան.';
+$PHPMAILER_LANG['invalid_address'] = 'Հասցեն սխալ է: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' փոստային սերվերի հետ չի աշխատում.';
+$PHPMAILER_LANG['provide_address'] = 'Անհրաժեշտ է տրամադրել գոնե մեկ ստացողի e-mail հասցե.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP -ի սխալ: չի հաջողվել ուղարկել հետևյալ ստացողների հասցեներին: ';
+$PHPMAILER_LANG['signing'] = 'Ստորագրման սխալ: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP -ի connect() ֆունկցիան չի հաջողվել';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP սերվերի սխալ: ';
+$PHPMAILER_LANG['variable_set'] = 'Չի հաջողվում ստեղծել կամ վերափոխել փոփոխականը: ';
+$PHPMAILER_LANG['extension_missing'] = 'Հավելվածը բացակայում է: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-id.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-id.php
new file mode 100644
index 0000000..212a11f
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-id.php
@@ -0,0 +1,31 @@
+
+ * @author @januridp
+ * @author Ian Mustafa
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Kesalahan SMTP: Tidak dapat mengotentikasi.';
+$PHPMAILER_LANG['connect_host'] = 'Kesalahan SMTP: Tidak dapat terhubung ke host SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Kesalahan SMTP: Data tidak diterima.';
+$PHPMAILER_LANG['empty_message'] = 'Isi pesan kosong';
+$PHPMAILER_LANG['encoding'] = 'Pengkodean karakter tidak dikenali: ';
+$PHPMAILER_LANG['execute'] = 'Tidak dapat menjalankan proses: ';
+$PHPMAILER_LANG['file_access'] = 'Tidak dapat mengakses berkas: ';
+$PHPMAILER_LANG['file_open'] = 'Kesalahan Berkas: Berkas tidak dapat dibuka: ';
+$PHPMAILER_LANG['from_failed'] = 'Alamat pengirim berikut mengakibatkan kesalahan: ';
+$PHPMAILER_LANG['instantiate'] = 'Tidak dapat menginisialisasi fungsi surel.';
+$PHPMAILER_LANG['invalid_address'] = 'Gagal terkirim, alamat surel tidak sesuai: ';
+$PHPMAILER_LANG['invalid_hostentry'] = 'Gagal terkirim, entri host tidak sesuai: ';
+$PHPMAILER_LANG['invalid_host'] = 'Gagal terkirim, host tidak sesuai: ';
+$PHPMAILER_LANG['provide_address'] = 'Harus tersedia minimal satu alamat tujuan';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer tidak didukung';
+$PHPMAILER_LANG['recipients_failed'] = 'Kesalahan SMTP: Alamat tujuan berikut menyebabkan kesalahan: ';
+$PHPMAILER_LANG['signing'] = 'Kesalahan dalam penandatangan SSL: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() gagal.';
+$PHPMAILER_LANG['smtp_error'] = 'Kesalahan pada pelayan SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Tidak dapat mengatur atau mengatur ulang variabel: ';
+$PHPMAILER_LANG['extension_missing'] = 'Ekstensi PHP tidak tersedia: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-it.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-it.php
new file mode 100644
index 0000000..08a6b73
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-it.php
@@ -0,0 +1,28 @@
+
+ * @author Stefano Sabatini
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP Error: Impossibile autenticarsi.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Impossibile connettersi all\'host SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Dati non accettati dal server.';
+$PHPMAILER_LANG['empty_message'] = 'Il corpo del messaggio è vuoto';
+$PHPMAILER_LANG['encoding'] = 'Codifica dei caratteri sconosciuta: ';
+$PHPMAILER_LANG['execute'] = 'Impossibile eseguire l\'operazione: ';
+$PHPMAILER_LANG['file_access'] = 'Impossibile accedere al file: ';
+$PHPMAILER_LANG['file_open'] = 'File Error: Impossibile aprire il file: ';
+$PHPMAILER_LANG['from_failed'] = 'I seguenti indirizzi mittenti hanno generato errore: ';
+$PHPMAILER_LANG['instantiate'] = 'Impossibile istanziare la funzione mail';
+$PHPMAILER_LANG['invalid_address'] = 'Impossibile inviare, l\'indirizzo email non è valido: ';
+$PHPMAILER_LANG['provide_address'] = 'Deve essere fornito almeno un indirizzo ricevente';
+$PHPMAILER_LANG['mailer_not_supported'] = 'Mailer non supportato';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: I seguenti indirizzi destinatari hanno generato un errore: ';
+$PHPMAILER_LANG['signing'] = 'Errore nella firma: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fallita.';
+$PHPMAILER_LANG['smtp_error'] = 'Errore del server SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Impossibile impostare o resettare la variabile: ';
+$PHPMAILER_LANG['extension_missing'] = 'Estensione mancante: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ja.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ja.php
new file mode 100644
index 0000000..c76f526
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ja.php
@@ -0,0 +1,29 @@
+
+ * @author Yoshi Sakai
+ * @author Arisophy
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTPエラー: 認証できませんでした。';
+$PHPMAILER_LANG['connect_host'] = 'SMTPエラー: SMTPホストに接続できませんでした。';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTPエラー: データが受け付けられませんでした。';
+$PHPMAILER_LANG['empty_message'] = 'メール本文が空です。';
+$PHPMAILER_LANG['encoding'] = '不明なエンコーディング: ';
+$PHPMAILER_LANG['execute'] = '実行できませんでした: ';
+$PHPMAILER_LANG['file_access'] = 'ファイルにアクセスできません: ';
+$PHPMAILER_LANG['file_open'] = 'ファイルエラー: ファイルを開けません: ';
+$PHPMAILER_LANG['from_failed'] = 'Fromアドレスを登録する際にエラーが発生しました: ';
+$PHPMAILER_LANG['instantiate'] = 'メール関数が正常に動作しませんでした。';
+$PHPMAILER_LANG['invalid_address'] = '不正なメールアドレス: ';
+$PHPMAILER_LANG['provide_address'] = '少なくとも1つメールアドレスを 指定する必要があります。';
+$PHPMAILER_LANG['mailer_not_supported'] = ' メーラーがサポートされていません。';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTPエラー: 次の受信者アドレスに 間違いがあります: ';
+$PHPMAILER_LANG['signing'] = '署名エラー: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP接続に失敗しました。';
+$PHPMAILER_LANG['smtp_error'] = 'SMTPサーバーエラー: ';
+$PHPMAILER_LANG['variable_set'] = '変数が存在しません: ';
+$PHPMAILER_LANG['extension_missing'] = '拡張機能が見つかりません: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ka.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ka.php
new file mode 100644
index 0000000..51fe403
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ka.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP შეცდომა: ავტორიზაცია შეუძლებელია.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP შეცდომა: SMTP სერვერთან დაკავშირება შეუძლებელია.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP შეცდომა: მონაცემები არ იქნა მიღებული.';
+$PHPMAILER_LANG['encoding'] = 'კოდირების უცნობი ტიპი: ';
+$PHPMAILER_LANG['execute'] = 'შეუძლებელია შემდეგი ბრძანების შესრულება: ';
+$PHPMAILER_LANG['file_access'] = 'შეუძლებელია წვდომა ფაილთან: ';
+$PHPMAILER_LANG['file_open'] = 'ფაილური სისტემის შეცდომა: არ იხსნება ფაილი: ';
+$PHPMAILER_LANG['from_failed'] = 'გამგზავნის არასწორი მისამართი: ';
+$PHPMAILER_LANG['instantiate'] = 'mail ფუნქციის გაშვება ვერ ხერხდება.';
+$PHPMAILER_LANG['provide_address'] = 'გთხოვთ მიუთითოთ ერთი ადრესატის e-mail მისამართი მაინც.';
+$PHPMAILER_LANG['mailer_not_supported'] = ' - საფოსტო სერვერის მხარდაჭერა არ არის.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP შეცდომა: შემდეგ მისამართებზე გაგზავნა ვერ მოხერხდა: ';
+$PHPMAILER_LANG['empty_message'] = 'შეტყობინება ცარიელია';
+$PHPMAILER_LANG['invalid_address'] = 'არ გაიგზავნა, e-mail მისამართის არასწორი ფორმატი: ';
+$PHPMAILER_LANG['signing'] = 'ხელმოწერის შეცდომა: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'შეცდომა SMTP სერვერთან დაკავშირებისას';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP სერვერის შეცდომა: ';
+$PHPMAILER_LANG['variable_set'] = 'შეუძლებელია შემდეგი ცვლადის შექმნა ან შეცვლა: ';
+$PHPMAILER_LANG['extension_missing'] = 'ბიბლიოთეკა არ არსებობს: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ko.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ko.php
new file mode 100644
index 0000000..8c97dd9
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ko.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP 오류: 인증할 수 없습니다.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP 오류: SMTP 호스트에 접속할 수 없습니다.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP 오류: 데이터가 받아들여지지 않았습니다.';
+$PHPMAILER_LANG['empty_message'] = '메세지 내용이 없습니다';
+$PHPMAILER_LANG['encoding'] = '알 수 없는 인코딩: ';
+$PHPMAILER_LANG['execute'] = '실행 불가: ';
+$PHPMAILER_LANG['file_access'] = '파일 접근 불가: ';
+$PHPMAILER_LANG['file_open'] = '파일 오류: 파일을 열 수 없습니다: ';
+$PHPMAILER_LANG['from_failed'] = '다음 From 주소에서 오류가 발생했습니다: ';
+$PHPMAILER_LANG['instantiate'] = 'mail 함수를 인스턴스화할 수 없습니다';
+$PHPMAILER_LANG['invalid_address'] = '잘못된 주소: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' 메일러는 지원되지 않습니다.';
+$PHPMAILER_LANG['provide_address'] = '적어도 한 개 이상의 수신자 메일 주소를 제공해야 합니다.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP 오류: 다음 수신자에서 오류가 발생했습니다: ';
+$PHPMAILER_LANG['signing'] = '서명 오류: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP 연결을 실패하였습니다.';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP 서버 오류: ';
+$PHPMAILER_LANG['variable_set'] = '변수 설정 및 초기화 불가: ';
+$PHPMAILER_LANG['extension_missing'] = '확장자 없음: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lt.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lt.php
new file mode 100644
index 0000000..4f115b1
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lt.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP klaida: autentifikacija nepavyko.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP klaida: nepavyksta prisijungti prie SMTP stoties.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP klaida: duomenys nepriimti.';
+$PHPMAILER_LANG['empty_message'] = 'Laiško turinys tuščias';
+$PHPMAILER_LANG['encoding'] = 'Neatpažinta koduotė: ';
+$PHPMAILER_LANG['execute'] = 'Nepavyko įvykdyti komandos: ';
+$PHPMAILER_LANG['file_access'] = 'Byla nepasiekiama: ';
+$PHPMAILER_LANG['file_open'] = 'Bylos klaida: Nepavyksta atidaryti: ';
+$PHPMAILER_LANG['from_failed'] = 'Neteisingas siuntėjo adresas: ';
+$PHPMAILER_LANG['instantiate'] = 'Nepavyko paleisti mail funkcijos.';
+$PHPMAILER_LANG['invalid_address'] = 'Neteisingas adresas: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' pašto stotis nepalaikoma.';
+$PHPMAILER_LANG['provide_address'] = 'Nurodykite bent vieną gavėjo adresą.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP klaida: nepavyko išsiųsti šiems gavėjams: ';
+$PHPMAILER_LANG['signing'] = 'Prisijungimo klaida: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP susijungimo klaida';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP stoties klaida: ';
+$PHPMAILER_LANG['variable_set'] = 'Nepavyko priskirti reikšmės kintamajam: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lv.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lv.php
new file mode 100644
index 0000000..679b18c
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-lv.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP kļūda: Autorizācija neizdevās.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Kļūda: Nevar izveidot savienojumu ar SMTP serveri.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Kļūda: Nepieņem informāciju.';
+$PHPMAILER_LANG['empty_message'] = 'Ziņojuma teksts ir tukšs';
+$PHPMAILER_LANG['encoding'] = 'Neatpazīts kodējums: ';
+$PHPMAILER_LANG['execute'] = 'Neizdevās izpildīt komandu: ';
+$PHPMAILER_LANG['file_access'] = 'Fails nav pieejams: ';
+$PHPMAILER_LANG['file_open'] = 'Faila kļūda: Nevar atvērt failu: ';
+$PHPMAILER_LANG['from_failed'] = 'Nepareiza sūtītāja adrese: ';
+$PHPMAILER_LANG['instantiate'] = 'Nevar palaist sūtīšanas funkciju.';
+$PHPMAILER_LANG['invalid_address'] = 'Nepareiza adrese: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' sūtītājs netiek atbalstīts.';
+$PHPMAILER_LANG['provide_address'] = 'Lūdzu, norādiet vismaz vienu adresātu.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP kļūda: neizdevās nosūtīt šādiem saņēmējiem: ';
+$PHPMAILER_LANG['signing'] = 'Autorizācijas kļūda: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP savienojuma kļūda';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP servera kļūda: ';
+$PHPMAILER_LANG['variable_set'] = 'Nevar piešķirt mainīgā vērtību: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-mg.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-mg.php
new file mode 100644
index 0000000..8a94f6a
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-mg.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Hadisoana SMTP: Tsy nahomby ny fanamarinana.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Tsy afaka mampifandray amin\'ny mpampiantrano SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP diso: tsy voarakitra ny angona.';
+$PHPMAILER_LANG['empty_message'] = 'Tsy misy ny votoaty mailaka.';
+$PHPMAILER_LANG['encoding'] = 'Tsy fantatra encoding: ';
+$PHPMAILER_LANG['execute'] = 'Tsy afaka manatanteraka ity baiko manaraka ity: ';
+$PHPMAILER_LANG['file_access'] = 'Tsy nahomby ny fidirana amin\'ity rakitra ity: ';
+$PHPMAILER_LANG['file_open'] = 'Hadisoana diso: Tsy afaka nanokatra ity file manaraka ity: ';
+$PHPMAILER_LANG['from_failed'] = 'Ny adiresy iraka manaraka dia diso: ';
+$PHPMAILER_LANG['instantiate'] = 'Tsy afaka nanomboka ny hetsika mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Tsy mety ny adiresy: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer tsy manohana.';
+$PHPMAILER_LANG['provide_address'] = 'Alefaso azafady iray adiresy iray farafahakeliny.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Tsy mety ireo mpanaraka ireto: ';
+$PHPMAILER_LANG['signing'] = 'Error nandritra ny sonia:';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Tsy nahomby ny fifandraisana tamin\'ny server SMTP.';
+$PHPMAILER_LANG['smtp_error'] = 'Fahadisoana tamin\'ny server SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Tsy azo atao ny mametraka na mamerina ny variable: ';
+$PHPMAILER_LANG['extension_missing'] = 'Tsy hita ny ampahany: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ms.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ms.php
new file mode 100644
index 0000000..71db338
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ms.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Ralat SMTP: Tidak dapat pengesahan.';
+$PHPMAILER_LANG['connect_host'] = 'Ralat SMTP: Tidak dapat menghubungi hos pelayan SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Ralat SMTP: Data tidak diterima oleh pelayan.';
+$PHPMAILER_LANG['empty_message'] = 'Tiada isi untuk mesej';
+$PHPMAILER_LANG['encoding'] = 'Pengekodan tidak diketahui: ';
+$PHPMAILER_LANG['execute'] = 'Tidak dapat melaksanakan: ';
+$PHPMAILER_LANG['file_access'] = 'Tidak dapat mengakses fail: ';
+$PHPMAILER_LANG['file_open'] = 'Ralat Fail: Tidak dapat membuka fail: ';
+$PHPMAILER_LANG['from_failed'] = 'Berikut merupakan ralat dari alamat e-mel: ';
+$PHPMAILER_LANG['instantiate'] = 'Tidak dapat memberi contoh fungsi e-mel.';
+$PHPMAILER_LANG['invalid_address'] = 'Alamat emel tidak sah: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' jenis penghantar emel tidak disokong.';
+$PHPMAILER_LANG['provide_address'] = 'Anda perlu menyediakan sekurang-kurangnya satu alamat e-mel penerima.';
+$PHPMAILER_LANG['recipients_failed'] = 'Ralat SMTP: Penerima e-mel berikut telah gagal: ';
+$PHPMAILER_LANG['signing'] = 'Ralat pada tanda tangan: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() telah gagal.';
+$PHPMAILER_LANG['smtp_error'] = 'Ralat pada pelayan SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Tidak boleh menetapkan atau menetapkan semula pembolehubah: ';
+$PHPMAILER_LANG['extension_missing'] = 'Sambungan hilang: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-nb.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-nb.php
new file mode 100644
index 0000000..65793ce
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-nb.php
@@ -0,0 +1,26 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP-fout: authenticatie mislukt.';
+$PHPMAILER_LANG['buggy_php'] = 'PHP versie gededecteerd die onderhavig is aan een bug die kan resulteren in gecorrumpeerde berichten. Om dit te voorkomen, gebruik SMTP voor het verzenden van berichten, zet de mail.add_x_header optie in uw php.ini file uit, gebruik MacOS of Linux, of pas de gebruikte PHP versie aan naar versie 7.0.17+ or 7.1.3+.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP-fout: kon niet verbinden met SMTP-host.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-fout: data niet geaccepteerd.';
+$PHPMAILER_LANG['empty_message'] = 'Berichttekst is leeg';
+$PHPMAILER_LANG['encoding'] = 'Onbekende codering: ';
+$PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: ';
+$PHPMAILER_LANG['extension_missing'] = 'Extensie afwezig: ';
+$PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: ';
+$PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen: ';
+$PHPMAILER_LANG['from_failed'] = 'Het volgende afzendersadres is mislukt: ';
+$PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.';
+$PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres: ';
+$PHPMAILER_LANG['invalid_header'] = 'Ongeldige header naam of waarde';
+$PHPMAILER_LANG['invalid_hostentry'] = 'Ongeldige hostentry: ';
+$PHPMAILER_LANG['invalid_host'] = 'Ongeldige host: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
+$PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';
+$PHPMAILER_LANG['signing'] = 'Signeerfout: ';
+$PHPMAILER_LANG['smtp_code'] = 'SMTP code: ';
+$PHPMAILER_LANG['smtp_code_ex'] = 'Aanvullende SMTP informatie: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Verbinding mislukt.';
+$PHPMAILER_LANG['smtp_detail'] = 'Detail: ';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfout: ';
+$PHPMAILER_LANG['variable_set'] = 'Kan de volgende variabele niet instellen of resetten: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pl.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pl.php
new file mode 100644
index 0000000..23caa71
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pl.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.';
+$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.';
+$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.';
+$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
+$PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
+$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: ';
+$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: ';
+$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: ';
+$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
+$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.';
+$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: ';
+$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
+$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
+$PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pt_br.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pt_br.php
new file mode 100644
index 0000000..5239865
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-pt_br.php
@@ -0,0 +1,38 @@
+
+ * @author Lucas Guimarães
+ * @author Phelipe Alves
+ * @author Fabio Beneditto
+ * @author Geidson Benício Coelho
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Erro de SMTP: Não foi possível autenticar.';
+$PHPMAILER_LANG['buggy_php'] = 'Sua versão do PHP é afetada por um bug que por resultar em messagens corrompidas. Para corrigir, mude para enviar usando SMTP, desative a opção mail.add_x_header em seu php.ini, mude para MacOS ou Linux, ou atualize seu PHP para versão 7.0.17+ ou 7.1.3+ ';
+$PHPMAILER_LANG['connect_host'] = 'Erro de SMTP: Não foi possível conectar ao servidor SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Erro de SMTP: Dados rejeitados.';
+$PHPMAILER_LANG['empty_message'] = 'Mensagem vazia';
+$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
+$PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
+$PHPMAILER_LANG['extension_missing'] = 'Extensão não existe: ';
+$PHPMAILER_LANG['file_access'] = 'Não foi possível acessar o arquivo: ';
+$PHPMAILER_LANG['file_open'] = 'Erro de Arquivo: Não foi possível abrir o arquivo: ';
+$PHPMAILER_LANG['from_failed'] = 'Os seguintes remetentes falharam: ';
+$PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.';
+$PHPMAILER_LANG['invalid_address'] = 'Endereço de e-mail inválido: ';
+$PHPMAILER_LANG['invalid_header'] = 'Nome ou valor de cabeçalho inválido';
+$PHPMAILER_LANG['invalid_hostentry'] = 'hostentry inválido: ';
+$PHPMAILER_LANG['invalid_host'] = 'host inválido: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
+$PHPMAILER_LANG['provide_address'] = 'Você deve informar pelo menos um destinatário.';
+$PHPMAILER_LANG['recipients_failed'] = 'Erro de SMTP: Os seguintes destinatários falharam: ';
+$PHPMAILER_LANG['signing'] = 'Erro de Assinatura: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
+$PHPMAILER_LANG['smtp_code'] = 'Código do servidor SMTP: ';
+$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
+$PHPMAILER_LANG['smtp_code_ex'] = 'Informações adicionais do servidor SMTP: ';
+$PHPMAILER_LANG['smtp_detail'] = 'Detalhes do servidor SMTP: ';
+$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ro.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ro.php
new file mode 100644
index 0000000..45bef91
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-ro.php
@@ -0,0 +1,33 @@
+
+ * @author Foster Snowhill
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Ошибка SMTP: ошибка авторизации.';
+$PHPMAILER_LANG['connect_host'] = 'Ошибка SMTP: не удается подключиться к SMTP-серверу.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Ошибка SMTP: данные не приняты.';
+$PHPMAILER_LANG['encoding'] = 'Неизвестная кодировка: ';
+$PHPMAILER_LANG['execute'] = 'Невозможно выполнить команду: ';
+$PHPMAILER_LANG['file_access'] = 'Нет доступа к файлу: ';
+$PHPMAILER_LANG['file_open'] = 'Файловая ошибка: не удаётся открыть файл: ';
+$PHPMAILER_LANG['from_failed'] = 'Неверный адрес отправителя: ';
+$PHPMAILER_LANG['instantiate'] = 'Невозможно запустить функцию mail().';
+$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['signing'] = 'Ошибка подписи: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Ошибка соединения с SMTP-сервером';
+$PHPMAILER_LANG['smtp_error'] = 'Ошибка SMTP-сервера: ';
+$PHPMAILER_LANG['variable_set'] = 'Невозможно установить или сбросить переменную: ';
+$PHPMAILER_LANG['extension_missing'] = 'Расширение отсутствует: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sk.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sk.php
new file mode 100644
index 0000000..028f5bc
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sk.php
@@ -0,0 +1,30 @@
+
+ * @author Peter Orlický
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP Error: Chyba autentifikácie.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Nebolo možné nadviazať spojenie so SMTP serverom.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Dáta neboli prijaté';
+$PHPMAILER_LANG['empty_message'] = 'Prázdne telo správy.';
+$PHPMAILER_LANG['encoding'] = 'Neznáme kódovanie: ';
+$PHPMAILER_LANG['execute'] = 'Nedá sa vykonať: ';
+$PHPMAILER_LANG['file_access'] = 'Súbor nebol nájdený: ';
+$PHPMAILER_LANG['file_open'] = 'File Error: Súbor sa otvoriť pre čítanie: ';
+$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 ';
+$PHPMAILER_LANG['signing'] = 'Chyba prihlasovania: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() zlyhalo.';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP chyba serveru: ';
+$PHPMAILER_LANG['variable_set'] = 'Nemožno nastaviť alebo resetovať premennú: ';
+$PHPMAILER_LANG['extension_missing'] = 'Chýba rozšírenie: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sl.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sl.php
new file mode 100644
index 0000000..3e00c25
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sl.php
@@ -0,0 +1,36 @@
+
+ * @author Filip Š
+ * @author Blaž Oražem
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP napaka: Avtentikacija ni uspela.';
+$PHPMAILER_LANG['buggy_php'] = 'Na vašo PHP različico vpliva napaka, ki lahko povzroči poškodovana sporočila. Če želite težavo odpraviti, preklopite na pošiljanje prek SMTP, onemogočite možnost mail.add_x_header v vaši php.ini datoteki, preklopite na MacOS ali Linux, ali nadgradite vašo PHP zaličico na 7.0.17+ ali 7.1.3+.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP napaka: Vzpostavljanje povezave s SMTP gostiteljem ni uspelo.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP napaka: Strežnik zavrača podatke.';
+$PHPMAILER_LANG['empty_message'] = 'E-poštno sporočilo nima vsebine.';
+$PHPMAILER_LANG['encoding'] = 'Nepoznan tip kodiranja: ';
+$PHPMAILER_LANG['execute'] = 'Operacija ni uspela: ';
+$PHPMAILER_LANG['extension_missing'] = 'Manjkajoča razširitev: ';
+$PHPMAILER_LANG['file_access'] = 'Nimam dostopa do datoteke: ';
+$PHPMAILER_LANG['file_open'] = 'Ne morem odpreti datoteke: ';
+$PHPMAILER_LANG['from_failed'] = 'Neveljaven e-naslov pošiljatelja: ';
+$PHPMAILER_LANG['instantiate'] = 'Ne morem inicializirati mail funkcije.';
+$PHPMAILER_LANG['invalid_address'] = 'E-poštno sporočilo ni bilo poslano. E-naslov je neveljaven: ';
+$PHPMAILER_LANG['invalid_header'] = 'Neveljavno ime ali vrednost glave';
+$PHPMAILER_LANG['invalid_hostentry'] = 'Neveljaven vnos gostitelja: ';
+$PHPMAILER_LANG['invalid_host'] = 'Neveljaven gostitelj: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer ni podprt.';
+$PHPMAILER_LANG['provide_address'] = 'Prosimo, vnesite vsaj enega naslovnika.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP napaka: Sledeči naslovniki so neveljavni: ';
+$PHPMAILER_LANG['signing'] = 'Napaka pri podpisovanju: ';
+$PHPMAILER_LANG['smtp_code'] = 'SMTP koda: ';
+$PHPMAILER_LANG['smtp_code_ex'] = 'Dodatne informacije o SMTP: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Ne morem vzpostaviti povezave s SMTP strežnikom.';
+$PHPMAILER_LANG['smtp_detail'] = 'Podrobnosti: ';
+$PHPMAILER_LANG['smtp_error'] = 'Napaka SMTP strežnika: ';
+$PHPMAILER_LANG['variable_set'] = 'Ne morem nastaviti oz. ponastaviti spremenljivke: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr.php
new file mode 100644
index 0000000..0b5280f
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr.php
@@ -0,0 +1,28 @@
+
+ * @author Miloš Milanović
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP грешка: аутентификација није успела.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP грешка: повезивање са SMTP сервером није успело.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP грешка: подаци нису прихваћени.';
+$PHPMAILER_LANG['empty_message'] = 'Садржај поруке је празан.';
+$PHPMAILER_LANG['encoding'] = 'Непознато кодирање: ';
+$PHPMAILER_LANG['execute'] = 'Није могуће извршити наредбу: ';
+$PHPMAILER_LANG['file_access'] = 'Није могуће приступити датотеци: ';
+$PHPMAILER_LANG['file_open'] = 'Није могуће отворити датотеку: ';
+$PHPMAILER_LANG['from_failed'] = 'SMTP грешка: слање са следећих адреса није успело: ';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP грешка: слање на следеће адресе није успело: ';
+$PHPMAILER_LANG['instantiate'] = 'Није могуће покренути mail функцију.';
+$PHPMAILER_LANG['invalid_address'] = 'Порука није послата. Неисправна адреса: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' мејлер није подржан.';
+$PHPMAILER_LANG['provide_address'] = 'Дефинишите бар једну адресу примаоца.';
+$PHPMAILER_LANG['signing'] = 'Грешка приликом пријаве: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Повезивање са SMTP сервером није успело.';
+$PHPMAILER_LANG['smtp_error'] = 'Грешка SMTP сервера: ';
+$PHPMAILER_LANG['variable_set'] = 'Није могуће задати нити ресетовати променљиву: ';
+$PHPMAILER_LANG['extension_missing'] = 'Недостаје проширење: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr_latn.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr_latn.php
new file mode 100644
index 0000000..6213832
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sr_latn.php
@@ -0,0 +1,28 @@
+
+ * @author Miloš Milanović
+ */
+
+$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: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sv.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sv.php
new file mode 100644
index 0000000..9872c19
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-sv.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP fel: Kunde inte autentisera.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP fel: Kunde inte ansluta till SMTP-server.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP fel: Data accepterades inte.';
+//$PHPMAILER_LANG['empty_message'] = 'Message body empty';
+$PHPMAILER_LANG['encoding'] = 'Okänt encode-format: ';
+$PHPMAILER_LANG['execute'] = 'Kunde inte köra: ';
+$PHPMAILER_LANG['file_access'] = 'Ingen åtkomst till fil: ';
+$PHPMAILER_LANG['file_open'] = 'Fil fel: Kunde inte öppna fil: ';
+$PHPMAILER_LANG['from_failed'] = 'Följande avsändaradress är felaktig: ';
+$PHPMAILER_LANG['instantiate'] = 'Kunde inte initiera e-postfunktion.';
+$PHPMAILER_LANG['invalid_address'] = 'Felaktig adress: ';
+$PHPMAILER_LANG['provide_address'] = 'Du måste ange minst en mottagares e-postadress.';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer stöds inte.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP fel: Följande mottagare är felaktig: ';
+$PHPMAILER_LANG['signing'] = 'Signeringsfel: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() misslyckades.';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP serverfel: ';
+$PHPMAILER_LANG['variable_set'] = 'Kunde inte definiera eller återställa variabel: ';
+$PHPMAILER_LANG['extension_missing'] = 'Tillägg ej tillgängligt: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tl.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tl.php
new file mode 100644
index 0000000..d15bed1
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tl.php
@@ -0,0 +1,28 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP Error: Hindi mapatotohanan.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Hindi makakonekta sa SMTP host.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Ang datos ay hindi naitanggap.';
+$PHPMAILER_LANG['empty_message'] = 'Walang laman ang mensahe';
+$PHPMAILER_LANG['encoding'] = 'Hindi alam ang encoding: ';
+$PHPMAILER_LANG['execute'] = 'Hindi maisasagawa: ';
+$PHPMAILER_LANG['file_access'] = 'Hindi ma-access ang file: ';
+$PHPMAILER_LANG['file_open'] = 'File Error: Hindi mabuksan ang file: ';
+$PHPMAILER_LANG['from_failed'] = 'Ang sumusunod na address ay nabigo: ';
+$PHPMAILER_LANG['instantiate'] = 'Hindi maisimulan ang instance ng mail function.';
+$PHPMAILER_LANG['invalid_address'] = 'Hindi wasto ang address na naibigay: ';
+$PHPMAILER_LANG['mailer_not_supported'] = 'Ang mailer ay hindi suportado.';
+$PHPMAILER_LANG['provide_address'] = 'Kailangan mong magbigay ng kahit isang email address na tatanggap.';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Ang mga sumusunod na tatanggap ay nabigo: ';
+$PHPMAILER_LANG['signing'] = 'Hindi ma-sign: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Ang SMTP connect() ay nabigo.';
+$PHPMAILER_LANG['smtp_error'] = 'Ang server ng SMTP ay nabigo: ';
+$PHPMAILER_LANG['variable_set'] = 'Hindi matatakda o ma-reset ang mga variables: ';
+$PHPMAILER_LANG['extension_missing'] = 'Nawawala ang extension: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tr.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tr.php
new file mode 100644
index 0000000..f938f80
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-tr.php
@@ -0,0 +1,31 @@
+
+ * @fixed by Boris Yurchenko
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Помилка SMTP: помилка авторизації.';
+$PHPMAILER_LANG['connect_host'] = 'Помилка SMTP: не вдається під\'єднатися до SMTP-серверу.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Помилка SMTP: дані не прийнято.';
+$PHPMAILER_LANG['encoding'] = 'Невідоме кодування: ';
+$PHPMAILER_LANG['execute'] = 'Неможливо виконати команду: ';
+$PHPMAILER_LANG['file_access'] = 'Немає доступу до файлу: ';
+$PHPMAILER_LANG['file_open'] = 'Помилка файлової системи: не вдається відкрити файл: ';
+$PHPMAILER_LANG['from_failed'] = 'Невірна адреса відправника: ';
+$PHPMAILER_LANG['instantiate'] = 'Неможливо запустити функцію mail().';
+$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['signing'] = 'Помилка підпису: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Помилка з\'єднання з SMTP-сервером';
+$PHPMAILER_LANG['smtp_error'] = 'Помилка SMTP-сервера: ';
+$PHPMAILER_LANG['variable_set'] = 'Неможливо встановити або скинути змінну: ';
+$PHPMAILER_LANG['extension_missing'] = 'Розширення відсутнє: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-vi.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-vi.php
new file mode 100644
index 0000000..d65576e
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-vi.php
@@ -0,0 +1,27 @@
+
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'Lỗi SMTP: Không thể xác thực.';
+$PHPMAILER_LANG['connect_host'] = 'Lỗi SMTP: Không thể kết nối máy chủ SMTP.';
+$PHPMAILER_LANG['data_not_accepted'] = 'Lỗi SMTP: Dữ liệu không được chấp nhận.';
+$PHPMAILER_LANG['empty_message'] = 'Không có nội dung';
+$PHPMAILER_LANG['encoding'] = 'Mã hóa không xác định: ';
+$PHPMAILER_LANG['execute'] = 'Không thực hiện được: ';
+$PHPMAILER_LANG['file_access'] = 'Không thể truy cập tệp tin ';
+$PHPMAILER_LANG['file_open'] = 'Lỗi Tập tin: Không thể mở tệp tin: ';
+$PHPMAILER_LANG['from_failed'] = 'Lỗi địa chỉ gửi đi: ';
+$PHPMAILER_LANG['instantiate'] = 'Không dùng được các hàm gửi thư.';
+$PHPMAILER_LANG['invalid_address'] = 'Đại chỉ emai không đúng: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' trình gửi thư không được hỗ trợ.';
+$PHPMAILER_LANG['provide_address'] = 'Bạn phải cung cấp ít nhất một địa chỉ người nhận.';
+$PHPMAILER_LANG['recipients_failed'] = 'Lỗi SMTP: lỗi địa chỉ người nhận: ';
+$PHPMAILER_LANG['signing'] = 'Lỗi đăng nhập: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Lỗi kết nối với SMTP';
+$PHPMAILER_LANG['smtp_error'] = 'Lỗi máy chủ smtp ';
+$PHPMAILER_LANG['variable_set'] = 'Không thể thiết lập hoặc thiết lập lại biến: ';
+//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh.php
new file mode 100644
index 0000000..35e4e70
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh.php
@@ -0,0 +1,29 @@
+
+ * @author Peter Dave Hello <@PeterDaveHello/>
+ * @author Jason Chiang
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP 錯誤:登入失敗。';
+$PHPMAILER_LANG['connect_host'] = 'SMTP 錯誤:無法連線到 SMTP 主機。';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP 錯誤:無法接受的資料。';
+$PHPMAILER_LANG['empty_message'] = '郵件內容為空';
+$PHPMAILER_LANG['encoding'] = '未知編碼: ';
+$PHPMAILER_LANG['execute'] = '無法執行:';
+$PHPMAILER_LANG['file_access'] = '無法存取檔案:';
+$PHPMAILER_LANG['file_open'] = '檔案錯誤:無法開啟檔案:';
+$PHPMAILER_LANG['from_failed'] = '發送地址錯誤:';
+$PHPMAILER_LANG['instantiate'] = '未知函數呼叫。';
+$PHPMAILER_LANG['invalid_address'] = '因為電子郵件地址無效,無法傳送: ';
+$PHPMAILER_LANG['mailer_not_supported'] = '不支援的發信客戶端。';
+$PHPMAILER_LANG['provide_address'] = '必須提供至少一個收件人地址。';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP 錯誤:以下收件人地址錯誤:';
+$PHPMAILER_LANG['signing'] = '電子簽章錯誤: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP 連線失敗';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP 伺服器錯誤: ';
+$PHPMAILER_LANG['variable_set'] = '無法設定或重設變數: ';
+$PHPMAILER_LANG['extension_missing'] = '遺失模組 Extension: ';
diff --git a/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh_cn.php b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh_cn.php
new file mode 100644
index 0000000..728a499
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/language/phpmailer.lang-zh_cn.php
@@ -0,0 +1,29 @@
+
+ * @author young
+ * @author Teddysun
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP 错误:登录失败。';
+$PHPMAILER_LANG['connect_host'] = 'SMTP 错误:无法连接到 SMTP 主机。';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP 错误:数据不被接受。';
+$PHPMAILER_LANG['empty_message'] = '邮件正文为空。';
+$PHPMAILER_LANG['encoding'] = '未知编码:';
+$PHPMAILER_LANG['execute'] = '无法执行:';
+$PHPMAILER_LANG['file_access'] = '无法访问文件:';
+$PHPMAILER_LANG['file_open'] = '文件错误:无法打开文件:';
+$PHPMAILER_LANG['from_failed'] = '发送地址错误:';
+$PHPMAILER_LANG['instantiate'] = '未知函数调用。';
+$PHPMAILER_LANG['invalid_address'] = '发送失败,电子邮箱地址是无效的:';
+$PHPMAILER_LANG['mailer_not_supported'] = '发信客户端不被支持。';
+$PHPMAILER_LANG['provide_address'] = '必须提供至少一个收件人地址。';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误:';
+$PHPMAILER_LANG['signing'] = '登录失败:';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP服务器连接失败。';
+$PHPMAILER_LANG['smtp_error'] = 'SMTP服务器出错:';
+$PHPMAILER_LANG['variable_set'] = '无法设置或重置变量:';
+$PHPMAILER_LANG['extension_missing'] = '丢失模块 Extension:';
diff --git a/02.php/extension/PHPMailer-6.6.0/src/Exception.php b/02.php/extension/PHPMailer-6.6.0/src/Exception.php
new file mode 100644
index 0000000..52eaf95
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/src/Exception.php
@@ -0,0 +1,40 @@
+
+ * @author Jim Jagielski (jimjag)
+ * @author Andy Prevost (codeworxtech)
+ * @author Brent R. Matzelle (original founder)
+ * @copyright 2012 - 2020 Marcus Bointon
+ * @copyright 2010 - 2012 Jim Jagielski
+ * @copyright 2004 - 2009 Andy Prevost
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @note This program is distributed in the hope that it will be useful - WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+namespace PHPMailer\PHPMailer;
+
+/**
+ * PHPMailer exception handler.
+ *
+ * @author Marcus Bointon
+ */
+class Exception extends \Exception
+{
+ /**
+ * Prettify error message output.
+ *
+ * @return string
+ */
+ public function errorMessage()
+ {
+ return '' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "
\n";
+ }
+}
diff --git a/02.php/extension/PHPMailer-6.6.0/src/OAuth.php b/02.php/extension/PHPMailer-6.6.0/src/OAuth.php
new file mode 100644
index 0000000..c1d5b77
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/src/OAuth.php
@@ -0,0 +1,139 @@
+
+ * @author Jim Jagielski (jimjag)
+ * @author Andy Prevost (codeworxtech)
+ * @author Brent R. Matzelle (original founder)
+ * @copyright 2012 - 2020 Marcus Bointon
+ * @copyright 2010 - 2012 Jim Jagielski
+ * @copyright 2004 - 2009 Andy Prevost
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @note This program is distributed in the hope that it will be useful - WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+namespace PHPMailer\PHPMailer;
+
+use League\OAuth2\Client\Grant\RefreshToken;
+use League\OAuth2\Client\Provider\AbstractProvider;
+use League\OAuth2\Client\Token\AccessToken;
+
+/**
+ * OAuth - OAuth2 authentication wrapper class.
+ * Uses the oauth2-client package from the League of Extraordinary Packages.
+ *
+ * @see http://oauth2-client.thephpleague.com
+ *
+ * @author Marcus Bointon (Synchro/coolbru)
+ */
+class OAuth implements OAuthTokenProvider
+{
+ /**
+ * An instance of the League OAuth Client Provider.
+ *
+ * @var AbstractProvider
+ */
+ protected $provider;
+
+ /**
+ * The current OAuth access token.
+ *
+ * @var AccessToken
+ */
+ protected $oauthToken;
+
+ /**
+ * The user's email address, usually used as the login ID
+ * and also the from address when sending email.
+ *
+ * @var string
+ */
+ protected $oauthUserEmail = '';
+
+ /**
+ * The client secret, generated in the app definition of the service you're connecting to.
+ *
+ * @var string
+ */
+ protected $oauthClientSecret = '';
+
+ /**
+ * The client ID, generated in the app definition of the service you're connecting to.
+ *
+ * @var string
+ */
+ protected $oauthClientId = '';
+
+ /**
+ * The refresh token, used to obtain new AccessTokens.
+ *
+ * @var string
+ */
+ protected $oauthRefreshToken = '';
+
+ /**
+ * OAuth constructor.
+ *
+ * @param array $options Associative array containing
+ * `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
+ */
+ public function __construct($options)
+ {
+ $this->provider = $options['provider'];
+ $this->oauthUserEmail = $options['userName'];
+ $this->oauthClientSecret = $options['clientSecret'];
+ $this->oauthClientId = $options['clientId'];
+ $this->oauthRefreshToken = $options['refreshToken'];
+ }
+
+ /**
+ * Get a new RefreshToken.
+ *
+ * @return RefreshToken
+ */
+ protected function getGrant()
+ {
+ return new RefreshToken();
+ }
+
+ /**
+ * Get a new AccessToken.
+ *
+ * @return AccessToken
+ */
+ protected function getToken()
+ {
+ return $this->provider->getAccessToken(
+ $this->getGrant(),
+ ['refresh_token' => $this->oauthRefreshToken]
+ );
+ }
+
+ /**
+ * Generate a base64-encoded OAuth token.
+ *
+ * @return string
+ */
+ public function getOauth64()
+ {
+ //Get a new token if it's not available or has expired
+ if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
+ $this->oauthToken = $this->getToken();
+ }
+
+ return base64_encode(
+ 'user=' .
+ $this->oauthUserEmail .
+ "\001auth=Bearer " .
+ $this->oauthToken .
+ "\001\001"
+ );
+ }
+}
diff --git a/02.php/extension/PHPMailer-6.6.0/src/OAuthTokenProvider.php b/02.php/extension/PHPMailer-6.6.0/src/OAuthTokenProvider.php
new file mode 100644
index 0000000..1155507
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/src/OAuthTokenProvider.php
@@ -0,0 +1,44 @@
+
+ * @author Jim Jagielski (jimjag)
+ * @author Andy Prevost (codeworxtech)
+ * @author Brent R. Matzelle (original founder)
+ * @copyright 2012 - 2020 Marcus Bointon
+ * @copyright 2010 - 2012 Jim Jagielski
+ * @copyright 2004 - 2009 Andy Prevost
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @note This program is distributed in the hope that it will be useful - WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+namespace PHPMailer\PHPMailer;
+
+/**
+ * OAuthTokenProvider - OAuth2 token provider interface.
+ * Provides base64 encoded OAuth2 auth strings for SMTP authentication.
+ *
+ * @see OAuth
+ * @see SMTP::authenticate()
+ *
+ * @author Peter Scopes (pdscopes)
+ * @author Marcus Bointon (Synchro/coolbru)
+ */
+interface OAuthTokenProvider
+{
+ /**
+ * Generate a base64-encoded OAuth token ensuring that the access token has not expired.
+ * The string to be base 64 encoded should be in the form:
+ * "user=\001auth=Bearer \001\001"
+ *
+ * @return string
+ */
+ public function getOauth64();
+}
diff --git a/02.php/extension/PHPMailer-6.6.0/src/PHPMailer.php b/02.php/extension/PHPMailer-6.6.0/src/PHPMailer.php
new file mode 100644
index 0000000..3ad1446
--- /dev/null
+++ b/02.php/extension/PHPMailer-6.6.0/src/PHPMailer.php
@@ -0,0 +1,5072 @@
+
+ * @author Jim Jagielski (jimjag)
+ * @author Andy Prevost (codeworxtech)
+ * @author Brent R. Matzelle (original founder)
+ * @copyright 2012 - 2020 Marcus Bointon
+ * @copyright 2010 - 2012 Jim Jagielski
+ * @copyright 2004 - 2009 Andy Prevost
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ * @note This program is distributed in the hope that it will be useful - WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+namespace PHPMailer\PHPMailer;
+
+/**
+ * PHPMailer - PHP email creation and transport class.
+ *
+ * @author Marcus Bointon (Synchro/coolbru)
+ * @author Jim Jagielski (jimjag)
+ * @author Andy Prevost (codeworxtech)
+ * @author Brent R. Matzelle (original founder)
+ */
+class PHPMailer
+{
+ const CHARSET_ASCII = 'us-ascii';
+ // const CHARSET_ISO88591 = 'iso-8859-1';
+ const CHARSET_ISO88591 = 'utf-8';
+ const CHARSET_UTF8 = 'utf-8';
+
+ const CONTENT_TYPE_PLAINTEXT = 'text/plain';
+ const CONTENT_TYPE_TEXT_CALENDAR = 'text/calendar';
+ const CONTENT_TYPE_TEXT_HTML = 'text/html';
+ const CONTENT_TYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative';
+ const CONTENT_TYPE_MULTIPART_MIXED = 'multipart/mixed';
+ const CONTENT_TYPE_MULTIPART_RELATED = 'multipart/related';
+
+ const ENCODING_7BIT = '7bit';
+ const ENCODING_8BIT = '8bit';
+ const ENCODING_BASE64 = 'base64';
+ const ENCODING_BINARY = 'binary';
+ const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
+
+ const ENCRYPTION_STARTTLS = 'tls';
+ const ENCRYPTION_SMTPS = 'ssl';
+
+ const ICAL_METHOD_REQUEST = 'REQUEST';
+ const ICAL_METHOD_PUBLISH = 'PUBLISH';
+ const ICAL_METHOD_REPLY = 'REPLY';
+ const ICAL_METHOD_ADD = 'ADD';
+ const ICAL_METHOD_CANCEL = 'CANCEL';
+ const ICAL_METHOD_REFRESH = 'REFRESH';
+ const ICAL_METHOD_COUNTER = 'COUNTER';
+ const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER';
+
+ /**
+ * Email priority.
+ * Options: null (default), 1 = High, 3 = Normal, 5 = low.
+ * When null, the header is not set at all.
+ *
+ * @var int|null
+ */
+ public $Priority;
+
+ /**
+ * The character set of the message.
+ *
+ * @var string
+ */
+ public $CharSet = self::CHARSET_ISO88591;
+
+ /**
+ * The MIME Content-type of the message.
+ *
+ * @var string
+ */
+ public $ContentType = self::CONTENT_TYPE_PLAINTEXT;
+
+ /**
+ * The message encoding.
+ * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
+ *
+ * @var string
+ */
+ public $Encoding = self::ENCODING_8BIT;
+
+ /**
+ * Holds the most recent mailer error message.
+ *
+ * @var string
+ */
+ public $ErrorInfo = '';
+
+ /**
+ * The From email address for the message.
+ *
+ * @var string
+ */
+ public $From = '';
+
+ /**
+ * The From name of the message.
+ *
+ * @var string
+ */
+ public $FromName = '';
+
+ /**
+ * The envelope sender of the message.
+ * This will usually be turned into a Return-Path header by the receiver,
+ * and is the address that bounces will be sent to.
+ * If not empty, will be passed via `-f` to sendmail or as the 'MAIL FROM' value over SMTP.
+ *
+ * @var string
+ */
+ public $Sender = '';
+
+ /**
+ * The Subject of the message.
+ *
+ * @var string
+ */
+ public $Subject = '';
+
+ /**
+ * An HTML or plain text message body.
+ * If HTML then call isHTML(true).
+ *
+ * @var string
+ */
+ public $Body = '';
+
+ /**
+ * The plain-text message body.
+ * This body can be read by mail clients that do not have HTML email
+ * capability such as mutt & Eudora.
+ * Clients that can read HTML will view the normal Body.
+ *
+ * @var string
+ */
+ public $AltBody = '';
+
+ /**
+ * An iCal message part body.
+ * Only supported in simple alt or alt_inline message types
+ * To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator.
+ *
+ * @see http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/
+ * @see http://kigkonsult.se/iCalcreator/
+ *
+ * @var string
+ */
+ public $Ical = '';
+
+ /**
+ * Value-array of "method" in Contenttype header "text/calendar"
+ *
+ * @var string[]
+ */
+ protected static $IcalMethods = [
+ self::ICAL_METHOD_REQUEST,
+ self::ICAL_METHOD_PUBLISH,
+ self::ICAL_METHOD_REPLY,
+ self::ICAL_METHOD_ADD,
+ self::ICAL_METHOD_CANCEL,
+ self::ICAL_METHOD_REFRESH,
+ self::ICAL_METHOD_COUNTER,
+ self::ICAL_METHOD_DECLINECOUNTER,
+ ];
+
+ /**
+ * The complete compiled MIME message body.
+ *
+ * @var string
+ */
+ protected $MIMEBody = '';
+
+ /**
+ * The complete compiled MIME message headers.
+ *
+ * @var string
+ */
+ protected $MIMEHeader = '';
+
+ /**
+ * Extra headers that createHeader() doesn't fold in.
+ *
+ * @var string
+ */
+ protected $mailHeader = '';
+
+ /**
+ * Word-wrap the message body to this number of chars.
+ * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
+ *
+ * @see static::STD_LINE_LENGTH
+ *
+ * @var int
+ */
+ public $WordWrap = 0;
+
+ /**
+ * Which method to use to send mail.
+ * Options: "mail", "sendmail", or "smtp".
+ *
+ * @var string
+ */
+ public $Mailer = 'mail';
+
+ /**
+ * The path to the sendmail program.
+ *
+ * @var string
+ */
+ public $Sendmail = '/usr/sbin/sendmail';
+
+ /**
+ * Whether mail() uses a fully sendmail-compatible MTA.
+ * One which supports sendmail's "-oi -f" options.
+ *
+ * @var bool
+ */
+ public $UseSendmailOptions = true;
+
+ /**
+ * The email address that a reading confirmation should be sent to, also known as read receipt.
+ *
+ * @var string
+ */
+ public $ConfirmReadingTo = '';
+
+ /**
+ * The hostname to use in the Message-ID header and as default HELO string.
+ * If empty, PHPMailer attempts to find one with, in order,
+ * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
+ * 'localhost.localdomain'.
+ *
+ * @see PHPMailer::$Helo
+ *
+ * @var string
+ */
+ public $Hostname = '';
+
+ /**
+ * An ID to be used in the Message-ID header.
+ * If empty, a unique id will be generated.
+ * You can set your own, but it must be in the format "",
+ * as defined in RFC5322 section 3.6.4 or it will be ignored.
+ *
+ * @see https://tools.ietf.org/html/rfc5322#section-3.6.4
+ *
+ * @var string
+ */
+ public $MessageID = '';
+
+ /**
+ * The message Date to be used in the Date header.
+ * If empty, the current date will be added.
+ *
+ * @var string
+ */
+ public $MessageDate = '';
+
+ /**
+ * SMTP hosts.
+ * Either a single hostname or multiple semicolon-delimited hostnames.
+ * You can also specify a different port
+ * for each host by using this format: [hostname:port]
+ * (e.g. "smtp1.example.com:25;smtp2.example.com").
+ * You can also specify encryption type, for example:
+ * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
+ * Hosts will be tried in order.
+ *
+ * @var string
+ */
+ public $Host = 'localhost';
+
+ /**
+ * The default SMTP server port.
+ *
+ * @var int
+ */
+ public $Port = 25;
+
+ /**
+ * The SMTP HELO/EHLO name used for the SMTP connection.
+ * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
+ * one with the same method described above for $Hostname.
+ *
+ * @see PHPMailer::$Hostname
+ *
+ * @var string
+ */
+ public $Helo = '';
+
+ /**
+ * What kind of encryption to use on the SMTP connection.
+ * Options: '', static::ENCRYPTION_STARTTLS, or static::ENCRYPTION_SMTPS.
+ *
+ * @var string
+ */
+ public $SMTPSecure = '';
+
+ /**
+ * Whether to enable TLS encryption automatically if a server supports it,
+ * even if `SMTPSecure` is not set to 'tls'.
+ * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid.
+ *
+ * @var bool
+ */
+ public $SMTPAutoTLS = true;
+
+ /**
+ * Whether to use SMTP authentication.
+ * Uses the Username and Password properties.
+ *
+ * @see PHPMailer::$Username
+ * @see PHPMailer::$Password
+ *
+ * @var bool
+ */
+ public $SMTPAuth = false;
+
+ /**
+ * Options array passed to stream_context_create when connecting via SMTP.
+ *
+ * @var array
+ */
+ public $SMTPOptions = [];
+
+ /**
+ * SMTP username.
+ *
+ * @var string
+ */
+ public $Username = '';
+
+ /**
+ * SMTP password.
+ *
+ * @var string
+ */
+ public $Password = '';
+
+ /**
+ * SMTP auth type.
+ * Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2, attempted in that order if not specified.
+ *
+ * @var string
+ */
+ public $AuthType = '';
+
+ /**
+ * An implementation of the PHPMailer OAuthTokenProvider interface.
+ *
+ * @var OAuthTokenProvider
+ */
+ protected $oauth;
+
+ /**
+ * The SMTP server timeout in seconds.
+ * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
+ *
+ * @var int
+ */
+ public $Timeout = 300;
+
+ /**
+ * Comma separated list of DSN notifications
+ * 'NEVER' under no circumstances a DSN must be returned to the sender.
+ * If you use NEVER all other notifications will be ignored.
+ * 'SUCCESS' will notify you when your mail has arrived at its destination.
+ * 'FAILURE' will arrive if an error occurred during delivery.
+ * 'DELAY' will notify you if there is an unusual delay in delivery, but the actual
+ * delivery's outcome (success or failure) is not yet decided.
+ *
+ * @see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY
+ */
+ public $dsn = '';
+
+ /**
+ * SMTP class debug output mode.
+ * Debug output level.
+ * Options:
+ * @see SMTP::DEBUG_OFF: No output
+ * @see SMTP::DEBUG_CLIENT: Client messages
+ * @see SMTP::DEBUG_SERVER: Client and server messages
+ * @see SMTP::DEBUG_CONNECTION: As SERVER plus connection status
+ * @see SMTP::DEBUG_LOWLEVEL: Noisy, low-level data output, rarely needed
+ *
+ * @see SMTP::$do_debug
+ *
+ * @var int
+ */
+ public $SMTPDebug = 0;
+
+ /**
+ * How to handle debug output.
+ * Options:
+ * * `echo` Output plain-text as-is, appropriate for CLI
+ * * `html` Output escaped, line breaks converted to `
`, appropriate for browser output
+ * * `error_log` Output to error log as configured in php.ini
+ * By default PHPMailer will use `echo` if run from a `cli` or `cli-server` SAPI, `html` otherwise.
+ * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
+ *
+ * ```php
+ * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
+ * ```
+ *
+ * Alternatively, you can pass in an instance of a PSR-3 compatible logger, though only `debug`
+ * level output is used:
+ *
+ * ```php
+ * $mail->Debugoutput = new myPsr3Logger;
+ * ```
+ *
+ * @see SMTP::$Debugoutput
+ *
+ * @var string|callable|\Psr\Log\LoggerInterface
+ */
+ public $Debugoutput = 'echo';
+
+ /**
+ * Whether to keep the SMTP connection open after each message.
+ * If this is set to true then the connection will remain open after a send,
+ * and closing the connection will require an explicit call to smtpClose().
+ * It's a good idea to use this if you are sending multiple messages as it reduces overhead.
+ * See the mailing list example for how to use it.
+ *
+ * @var bool
+ */
+ public $SMTPKeepAlive = false;
+
+ /**
+ * Whether to split multiple to addresses into multiple messages
+ * or send them all in one message.
+ * Only supported in `mail` and `sendmail` transports, not in SMTP.
+ *
+ * @var bool
+ *
+ * @deprecated 6.0.0 PHPMailer isn't a mailing list manager!
+ */
+ public $SingleTo = false;
+
+ /**
+ * Storage for addresses when SingleTo is enabled.
+ *
+ * @var array
+ */
+ protected $SingleToArray = [];
+
+ /**
+ * Whether to generate VERP addresses on send.
+ * Only applicable when sending via SMTP.
+ *
+ * @see https://en.wikipedia.org/wiki/Variable_envelope_return_path
+ * @see http://www.postfix.org/VERP_README.html Postfix VERP info
+ *
+ * @var bool
+ */
+ public $do_verp = false;
+
+ /**
+ * Whether to allow sending messages with an empty body.
+ *
+ * @var bool
+ */
+ public $AllowEmpty = false;
+
+ /**
+ * DKIM selector.
+ *
+ * @var string
+ */
+ public $DKIM_selector = '';
+
+ /**
+ * DKIM Identity.
+ * Usually the email address used as the source of the email.
+ *
+ * @var string
+ */
+ public $DKIM_identity = '';
+
+ /**
+ * DKIM passphrase.
+ * Used if your key is encrypted.
+ *
+ * @var string
+ */
+ public $DKIM_passphrase = '';
+
+ /**
+ * DKIM signing domain name.
+ *
+ * @example 'example.com'
+ *
+ * @var string
+ */
+ public $DKIM_domain = '';
+
+ /**
+ * DKIM Copy header field values for diagnostic use.
+ *
+ * @var bool
+ */
+ public $DKIM_copyHeaderFields = true;
+
+ /**
+ * DKIM Extra signing headers.
+ *
+ * @example ['List-Unsubscribe', 'List-Help']
+ *
+ * @var array
+ */
+ public $DKIM_extraHeaders = [];
+
+ /**
+ * DKIM private key file path.
+ *
+ * @var string
+ */
+ public $DKIM_private = '';
+
+ /**
+ * DKIM private key string.
+ *
+ * If set, takes precedence over `$DKIM_private`.
+ *
+ * @var string
+ */
+ public $DKIM_private_string = '';
+
+ /**
+ * Callback Action function name.
+ *
+ * The function that handles the result of the send email action.
+ * It is called out by send() for each email sent.
+ *
+ * Value can be any php callable: http://www.php.net/is_callable
+ *
+ * Parameters:
+ * bool $result result of the send action
+ * array $to email addresses of the recipients
+ * array $cc cc email addresses
+ * array $bcc bcc email addresses
+ * string $subject the subject
+ * string $body the email body
+ * string $from email address of sender
+ * string $extra extra information of possible use
+ * "smtp_transaction_id' => last smtp transaction id
+ *
+ * @var string
+ */
+ public $action_function = '';
+
+ /**
+ * What to put in the X-Mailer header.
+ * Options: An empty string for PHPMailer default, whitespace/null for none, or a string to use.
+ *
+ * @var string|null
+ */
+ public $XMailer = '';
+
+ /**
+ * Which validator to use by default when validating email addresses.
+ * May be a callable to inject your own validator, but there are several built-in validators.
+ * The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option.
+ *
+ * @see PHPMailer::validateAddress()
+ *
+ * @var string|callable
+ */
+ public static $validator = 'php';
+
+ /**
+ * An instance of the SMTP sender class.
+ *
+ * @var SMTP
+ */
+ protected $smtp;
+
+ /**
+ * The array of 'to' names and addresses.
+ *
+ * @var array
+ */
+ protected $to = [];
+
+ /**
+ * The array of 'cc' names and addresses.
+ *
+ * @var array
+ */
+ protected $cc = [];
+
+ /**
+ * The array of 'bcc' names and addresses.
+ *
+ * @var array
+ */
+ protected $bcc = [];
+
+ /**
+ * The array of reply-to names and addresses.
+ *
+ * @var array
+ */
+ protected $ReplyTo = [];
+
+ /**
+ * An array of all kinds of addresses.
+ * Includes all of $to, $cc, $bcc.
+ *
+ * @see PHPMailer::$to
+ * @see PHPMailer::$cc
+ * @see PHPMailer::$bcc
+ *
+ * @var array
+ */
+ protected $all_recipients = [];
+
+ /**
+ * An array of names and addresses queued for validation.
+ * In send(), valid and non duplicate entries are moved to $all_recipients
+ * and one of $to, $cc, or $bcc.
+ * This array is used only for addresses with IDN.
+ *
+ * @see PHPMailer::$to
+ * @see PHPMailer::$cc
+ * @see PHPMailer::$bcc
+ * @see PHPMailer::$all_recipients
+ *
+ * @var array
+ */
+ protected $RecipientsQueue = [];
+
+ /**
+ * An array of reply-to names and addresses queued for validation.
+ * In send(), valid and non duplicate entries are moved to $ReplyTo.
+ * This array is used only for addresses with IDN.
+ *
+ * @see PHPMailer::$ReplyTo
+ *
+ * @var array
+ */
+ protected $ReplyToQueue = [];
+
+ /**
+ * The array of attachments.
+ *
+ * @var array
+ */
+ protected $attachment = [];
+
+ /**
+ * The array of custom headers.
+ *
+ * @var array
+ */
+ protected $CustomHeader = [];
+
+ /**
+ * The most recent Message-ID (including angular brackets).
+ *
+ * @var string
+ */
+ protected $lastMessageID = '';
+
+ /**
+ * The message's MIME type.
+ *
+ * @var string
+ */
+ protected $message_type = '';
+
+ /**
+ * The array of MIME boundary strings.
+ *
+ * @var array
+ */
+ protected $boundary = [];
+
+ /**
+ * The array of available text strings for the current language.
+ *
+ * @var array
+ */
+ protected $language = [];
+
+ /**
+ * The number of errors encountered.
+ *
+ * @var int
+ */
+ protected $error_count = 0;
+
+ /**
+ * The S/MIME certificate file path.
+ *
+ * @var string
+ */
+ protected $sign_cert_file = '';
+
+ /**
+ * The S/MIME key file path.
+ *
+ * @var string
+ */
+ protected $sign_key_file = '';
+
+ /**
+ * The optional S/MIME extra certificates ("CA Chain") file path.
+ *
+ * @var string
+ */
+ protected $sign_extracerts_file = '';
+
+ /**
+ * The S/MIME password for the key.
+ * Used only if the key is encrypted.
+ *
+ * @var string
+ */
+ protected $sign_key_pass = '';
+
+ /**
+ * Whether to throw exceptions for errors.
+ *
+ * @var bool
+ */
+ protected $exceptions = false;
+
+ /**
+ * Unique ID used for message ID and boundaries.
+ *
+ * @var string
+ */
+ protected $uniqueid = '';
+
+ /**
+ * The PHPMailer Version number.
+ *
+ * @var string
+ */
+ const VERSION = '6.6.0';
+
+ /**
+ * Error severity: message only, continue processing.
+ *
+ * @var int
+ */
+ const STOP_MESSAGE = 0;
+
+ /**
+ * Error severity: message, likely ok to continue processing.
+ *
+ * @var int
+ */
+ const STOP_CONTINUE = 1;
+
+ /**
+ * Error severity: message, plus full stop, critical error reached.
+ *
+ * @var int
+ */
+ const STOP_CRITICAL = 2;
+
+ /**
+ * The SMTP standard CRLF line break.
+ * If you want to change line break format, change static::$LE, not this.
+ */
+ const CRLF = "\r\n";
+
+ /**
+ * "Folding White Space" a white space string used for line folding.
+ */
+ const FWS = ' ';
+
+ /**
+ * SMTP RFC standard line ending; Carriage Return, Line Feed.
+ *
+ * @var string
+ */
+ protected static $LE = self::CRLF;
+
+ /**
+ * The maximum line length supported by mail().
+ *
+ * Background: mail() will sometimes corrupt messages
+ * with headers headers longer than 65 chars, see #818.
+ *
+ * @var int
+ */
+ const MAIL_MAX_LINE_LENGTH = 63;
+
+ /**
+ * The maximum line length allowed by RFC 2822 section 2.1.1.
+ *
+ * @var int
+ */
+ const MAX_LINE_LENGTH = 998;
+
+ /**
+ * The lower maximum line length allowed by RFC 2822 section 2.1.1.
+ * This length does NOT include the line break
+ * 76 means that lines will be 77 or 78 chars depending on whether
+ * the line break format is LF or CRLF; both are valid.
+ *
+ * @var int
+ */
+ const STD_LINE_LENGTH = 76;
+
+ /**
+ * Constructor.
+ *
+ * @param bool $exceptions Should we throw external exceptions?
+ */
+ public function __construct($exceptions = null)
+ {
+ if (null !== $exceptions) {
+ $this->exceptions = (bool) $exceptions;
+ }
+ //Pick an appropriate debug output format automatically
+ $this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html');
+ }
+
+ /**
+ * Destructor.
+ */
+ public function __destruct()
+ {
+ //Close any open SMTP connection nicely
+ $this->smtpClose();
+ }
+
+ /**
+ * Call mail() in a safe_mode-aware fashion.
+ * Also, unless sendmail_path points to sendmail (or something that
+ * claims to be sendmail), don't pass params (not a perfect fix,
+ * but it will do).
+ *
+ * @param string $to To
+ * @param string $subject Subject
+ * @param string $body Message Body
+ * @param string $header Additional Header(s)
+ * @param string|null $params Params
+ *
+ * @return bool
+ */
+ private function mailPassthru($to, $subject, $body, $header, $params)
+ {
+ //Check overloading of mail function to avoid double-encoding
+ if (ini_get('mbstring.func_overload') & 1) {
+ $subject = $this->secureHeader($subject);
+ } else {
+ $subject = $this->encodeHeader($this->secureHeader($subject));
+ }
+ //Calling mail() with null params breaks
+ $this->edebug('Sending with mail()');
+ $this->edebug('Sendmail path: ' . ini_get('sendmail_path'));
+ $this->edebug("Envelope sender: {$this->Sender}");
+ $this->edebug("To: {$to}");
+ $this->edebug("Subject: {$subject}");
+ $this->edebug("Headers: {$header}");
+ if (!$this->UseSendmailOptions || null === $params) {
+ $result = @mail($to, $subject, $body, $header);
+ } else {
+ $this->edebug("Additional params: {$params}");
+ $result = @mail($to, $subject, $body, $header, $params);
+ }
+ $this->edebug('Result: ' . ($result ? 'true' : 'false'));
+ return $result;
+ }
+
+ /**
+ * Output debugging info via a user-defined method.
+ * Only generates output if debug output is enabled.
+ *
+ * @see PHPMailer::$Debugoutput
+ * @see PHPMailer::$SMTPDebug
+ *
+ * @param string $str
+ */
+ protected function edebug($str)
+ {
+ if ($this->SMTPDebug <= 0) {
+ return;
+ }
+ //Is this a PSR-3 logger?
+ if ($this->Debugoutput instanceof \Psr\Log\LoggerInterface) {
+ $this->Debugoutput->debug($str);
+
+ return;
+ }
+ //Avoid clash with built-in function names
+ if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) {
+ call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
+
+ return;
+ }
+ switch ($this->Debugoutput) {
+ case 'error_log':
+ //Don't output, just log
+ /** @noinspection ForgottenDebugOutputInspection */
+ error_log($str);
+ break;
+ case 'html':
+ //Cleans up output a bit for a better looking, HTML-safe output
+ echo htmlentities(
+ preg_replace('/[\r\n]+/', '', $str),
+ ENT_QUOTES,
+ 'UTF-8'
+ ), "
\n";
+ break;
+ case 'echo':
+ default:
+ //Normalize line breaks
+ $str = preg_replace('/\r\n|\r/m', "\n", $str);
+ echo gmdate('Y-m-d H:i:s'),
+ "\t",
+ //Trim trailing space
+ trim(
+ //Indent for readability, except for trailing break
+ str_replace(
+ "\n",
+ "\n \t ",
+ trim($str)
+ )
+ ),
+ "\n";
+ }
+ }
+
+ /**
+ * Sets message type to HTML or plain.
+ *
+ * @param bool $isHtml True for HTML mode
+ */
+ public function isHTML($isHtml = true)
+ {
+ if ($isHtml) {
+ $this->ContentType = static::CONTENT_TYPE_TEXT_HTML;
+ } else {
+ $this->ContentType = static::CONTENT_TYPE_PLAINTEXT;
+ }
+ }
+
+ /**
+ * Send messages using SMTP.
+ */
+ public function isSMTP()
+ {
+ $this->Mailer = 'smtp';
+ }
+
+ /**
+ * Send messages using PHP's mail() function.
+ */
+ public function isMail()
+ {
+ $this->Mailer = 'mail';
+ }
+
+ /**
+ * Send messages using $Sendmail.
+ */
+ public function isSendmail()
+ {
+ $ini_sendmail_path = ini_get('sendmail_path');
+
+ if (false === stripos($ini_sendmail_path, 'sendmail')) {
+ $this->Sendmail = '/usr/sbin/sendmail';
+ } else {
+ $this->Sendmail = $ini_sendmail_path;
+ }
+ $this->Mailer = 'sendmail';
+ }
+
+ /**
+ * Send messages using qmail.
+ */
+ public function isQmail()
+ {
+ $ini_sendmail_path = ini_get('sendmail_path');
+
+ if (false === stripos($ini_sendmail_path, 'qmail')) {
+ $this->Sendmail = '/var/qmail/bin/qmail-inject';
+ } else {
+ $this->Sendmail = $ini_sendmail_path;
+ }
+ $this->Mailer = 'qmail';
+ }
+
+ /**
+ * Add a "To" address.
+ *
+ * @param string $address The email address to send to
+ * @param string $name
+ *
+ * @throws Exception
+ *
+ * @return bool true on success, false if address already used or invalid in some way
+ */
+ public function addAddress($address, $name = '')
+ {
+ return $this->addOrEnqueueAnAddress('to', $address, $name);
+ }
+
+ /**
+ * Add a "CC" address.
+ *
+ * @param string $address The email address to send to
+ * @param string $name
+ *
+ * @throws Exception
+ *
+ * @return bool true on success, false if address already used or invalid in some way
+ */
+ public function addCC($address, $name = '')
+ {
+ return $this->addOrEnqueueAnAddress('cc', $address, $name);
+ }
+
+ /**
+ * Add a "BCC" address.
+ *
+ * @param string $address The email address to send to
+ * @param string $name
+ *
+ * @throws Exception
+ *
+ * @return bool true on success, false if address already used or invalid in some way
+ */
+ public function addBCC($address, $name = '')
+ {
+ return $this->addOrEnqueueAnAddress('bcc', $address, $name);
+ }
+
+ /**
+ * Add a "Reply-To" address.
+ *
+ * @param string $address The email address to reply to
+ * @param string $name
+ *
+ * @throws Exception
+ *
+ * @return bool true on success, false if address already used or invalid in some way
+ */
+ public function addReplyTo($address, $name = '')
+ {
+ return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
+ }
+
+ /**
+ * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer
+ * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still
+ * be modified after calling this function), addition of such addresses is delayed until send().
+ * Addresses that have been added already return false, but do not throw exceptions.
+ *
+ * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
+ * @param string $address The email address to send, resp. to reply to
+ * @param string $name
+ *
+ * @throws Exception
+ *
+ * @return bool true on success, false if address already used or invalid in some way
+ */
+ protected function addOrEnqueueAnAddress($kind, $address, $name)
+ {
+ $address = trim($address);
+ $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+ $pos = strrpos($address, '@');
+ if (false === $pos) {
+ //At-sign is missing.
+ $error_message = sprintf(
+ '%s (%s): %s',
+ $this->lang('invalid_address'),
+ $kind,
+ $address
+ );
+ $this->setError($error_message);
+ $this->edebug($error_message);
+ if ($this->exceptions) {
+ throw new Exception($error_message);
+ }
+
+ return false;
+ }
+ $params = [$kind, $address, $name];
+ //Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
+ if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
+ if ('Reply-To' !== $kind) {
+ if (!array_key_exists($address, $this->RecipientsQueue)) {
+ $this->RecipientsQueue[$address] = $params;
+
+ return true;
+ }
+ } elseif (!array_key_exists($address, $this->ReplyToQueue)) {
+ $this->ReplyToQueue[$address] = $params;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ //Immediately add standard addresses without IDN.
+ return call_user_func_array([$this, 'addAnAddress'], $params);
+ }
+
+ /**
+ * 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.
+ *
+ * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
+ * @param string $address The email address to send, resp. to reply to
+ * @param string $name
+ *
+ * @throws Exception
+ *
+ * @return bool true on success, false if address already used or invalid in some way
+ */
+ protected function addAnAddress($kind, $address, $name = '')
+ {
+ if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
+ $error_message = sprintf(
+ '%s: %s',
+ $this->lang('Invalid recipient kind'),
+ $kind
+ );
+ $this->setError($error_message);
+ $this->edebug($error_message);
+ if ($this->exceptions) {
+ throw new Exception($error_message);
+ }
+
+ return false;
+ }
+ if (!static::validateAddress($address)) {
+ $error_message = sprintf(
+ '%s (%s): %s',
+ $this->lang('invalid_address'),
+ $kind,
+ $address
+ );
+ $this->setError($error_message);
+ $this->edebug($error_message);
+ if ($this->exceptions) {
+ throw new Exception($error_message);
+ }
+
+ return false;
+ }
+ if ('Reply-To' !== $kind) {
+ if (!array_key_exists(strtolower($address), $this->all_recipients)) {
+ $this->{$kind}[] = [$address, $name];
+ $this->all_recipients[strtolower($address)] = true;
+
+ return true;
+ }
+ } elseif (!array_key_exists(strtolower($address), $this->ReplyTo)) {
+ $this->ReplyTo[strtolower($address)] = [$address, $name];
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
+ * of the form "display name " into an array of name/address pairs.
+ * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
+ * Note that quotes in the name part are removed.
+ *
+ * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
+ *
+ * @param string $addrstr The address list string
+ * @param bool $useimap Whether to use the IMAP extension to parse the list
+ * @param string $charset The charset to use when decoding the address list string.
+ *
+ * @return array
+ */
+ public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
+ {
+ $addresses = [];
+ if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
+ //Use this built-in parser if it's available
+ $list = imap_rfc822_parse_adrlist($addrstr, '');
+ // Clear any potential IMAP errors to get rid of notices being thrown at end of script.
+ imap_errors();
+ foreach ($list as $address) {
+ if (
+ '.SYNTAX-ERROR.' !== $address->host &&
+ static::validateAddress($address->mailbox . '@' . $address->host)
+ ) {
+ //Decode the name part if it's present and encoded
+ if (
+ property_exists($address, 'personal') &&
+ //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
+ defined('MB_CASE_UPPER') &&
+ preg_match('/^=\?.*\?=$/s', $address->personal)
+ ) {
+ $origCharset = mb_internal_encoding();
+ mb_internal_encoding($charset);
+ //Undo any RFC2047-encoded spaces-as-underscores
+ $address->personal = str_replace('_', '=20', $address->personal);
+ //Decode the name
+ $address->personal = mb_decode_mimeheader($address->personal);
+ mb_internal_encoding($origCharset);
+ }
+
+ $addresses[] = [
+ 'name' => (property_exists($address, 'personal') ? $address->personal : ''),
+ 'address' => $address->mailbox . '@' . $address->host,
+ ];
+ }
+ }
+ } else {
+ //Use this simpler parser
+ $list = explode(',', $addrstr);
+ foreach ($list as $address) {
+ $address = trim($address);
+ //Is there a separate name part?
+ if (strpos($address, '<') === false) {
+ //No separate name, just use the whole thing
+ if (static::validateAddress($address)) {
+ $addresses[] = [
+ 'name' => '',
+ 'address' => $address,
+ ];
+ }
+ } else {
+ list($name, $email) = explode('<', $address);
+ $email = trim(str_replace('>', '', $email));
+ $name = trim($name);
+ if (static::validateAddress($email)) {
+ //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
+ //If this name is encoded, decode it
+ if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) {
+ $origCharset = mb_internal_encoding();
+ mb_internal_encoding($charset);
+ //Undo any RFC2047-encoded spaces-as-underscores
+ $name = str_replace('_', '=20', $name);
+ //Decode the name
+ $name = mb_decode_mimeheader($name);
+ mb_internal_encoding($origCharset);
+ }
+ $addresses[] = [
+ //Remove any surrounding quotes and spaces from the name
+ 'name' => trim($name, '\'" '),
+ 'address' => $email,
+ ];
+ }
+ }
+ }
+ }
+
+ return $addresses;
+ }
+
+ /**
+ * Set the From and FromName properties.
+ *
+ * @param string $address
+ * @param string $name
+ * @param bool $auto Whether to also set the Sender address, defaults to true
+ *
+ * @throws Exception
+ *
+ * @return bool
+ */
+ public function setFrom($address, $name = '', $auto = true)
+ {
+ $address = trim($address);
+ $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+ //Don't validate now addresses with IDN. Will be done in send().
+ $pos = strrpos($address, '@');
+ if (
+ (false === $pos)
+ || ((!$this->has8bitChars(substr($address, ++$pos)) || !static::idnSupported())
+ && !static::validateAddress($address))
+ ) {
+ $error_message = sprintf(
+ '%s (From): %s',
+ $this->lang('invalid_address'),
+ $address
+ );
+ $this->setError($error_message);
+ $this->edebug($error_message);
+ if ($this->exceptions) {
+ throw new Exception($error_message);
+ }
+
+ return false;
+ }
+ $this->From = $address;
+ $this->FromName = $name;
+ if ($auto && empty($this->Sender)) {
+ $this->Sender = $address;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return the Message-ID header of the last email.
+ * Technically this is the value from the last time the headers were created,
+ * but it's also the message ID of the last sent message except in
+ * pathological cases.
+ *
+ * @return string
+ */
+ public function getLastMessageID()
+ {
+ return $this->lastMessageID;
+ }
+
+ /**
+ * Check that a string looks like an email address.
+ * Validation patterns supported:
+ * * `auto` Pick best pattern automatically;
+ * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0;
+ * * `pcre` Use old PCRE implementation;
+ * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
+ * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
+ * * `noregex` Don't use a regex: super fast, really dumb.
+ * Alternatively you may pass in a callable to inject your own validator, for example:
+ *
+ * ```php
+ * PHPMailer::validateAddress('user@example.com', function($address) {
+ * return (strpos($address, '@') !== false);
+ * });
+ * ```
+ *
+ * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
+ *
+ * @param string $address The email address to check
+ * @param string|callable $patternselect Which pattern to use
+ *
+ * @return bool
+ */
+ public static function validateAddress($address, $patternselect = null)
+ {
+ if (null === $patternselect) {
+ $patternselect = static::$validator;
+ }
+ //Don't allow strings as callables, see SECURITY.md and CVE-2021-3603
+ if (is_callable($patternselect) && !is_string($patternselect)) {
+ return call_user_func($patternselect, $address);
+ }
+ //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
+ if (strpos($address, "\n") !== false || strpos($address, "\r") !== false) {
+ return false;
+ }
+ switch ($patternselect) {
+ case 'pcre': //Kept for BC
+ case 'pcre8':
+ /*
+ * A more complex and more permissive version of the RFC5322 regex on which FILTER_VALIDATE_EMAIL
+ * is based.
+ * In addition to the addresses allowed by filter_var, also permits:
+ * * dotless domains: `a@b`
+ * * comments: `1234 @ local(blah) .machine .example`
+ * * quoted elements: `'"test blah"@example.org'`
+ * * numeric TLDs: `a@b.123`
+ * * unbracketed IPv4 literals: `a@192.168.0.1`
+ * * IPv6 literals: 'first.last@[IPv6:a1::]'
+ * Not all of these will necessarily work for sending!
+ *
+ * @see http://squiloople.com/2009/12/20/email-address-validation/
+ * @copyright 2009-2010 Michael Rushton
+ * Feel free to use and redistribute this code. But please keep this copyright notice.
+ */
+ return (bool) preg_match(
+ '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
+ '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
+ '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
+ '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
+ '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
+ '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
+ '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
+ '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
+ '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
+ $address
+ );
+ case 'html5':
+ /*
+ * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
+ *
+ * @see https://html.spec.whatwg.org/#e-mail-state-(type=email)
+ */
+ return (bool) preg_match(
+ '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
+ '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
+ $address
+ );
+ case 'php':
+ default:
+ return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
+ }
+ }
+
+ /**
+ * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the
+ * `intl` and `mbstring` PHP extensions.
+ *
+ * @return bool `true` if required functions for IDN support are present
+ */
+ public static function idnSupported()
+ {
+ return function_exists('idn_to_ascii') && function_exists('mb_convert_encoding');
+ }
+
+ /**
+ * Converts IDN in given email address to its ASCII form, also known as punycode, if possible.
+ * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet.
+ * This function silently returns unmodified address if:
+ * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form)
+ * - Conversion to punycode is impossible (e.g. required PHP functions are not available)
+ * or fails for any reason (e.g. domain contains characters not allowed in an IDN).
+ *
+ * @see PHPMailer::$CharSet
+ *
+ * @param string $address The email address to convert
+ *
+ * @return string The encoded address in ASCII form
+ */
+ public function punyencodeAddress($address)
+ {
+ //Verify we have required functions, CharSet, and at-sign.
+ $pos = strrpos($address, '@');
+ if (
+ !empty($this->CharSet) &&
+ false !== $pos &&
+ static::idnSupported()
+ ) {
+ $domain = substr($address, ++$pos);
+ //Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
+ if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $this->CharSet)) {
+ //Convert the domain from whatever charset it's in to UTF-8
+ $domain = mb_convert_encoding($domain, self::CHARSET_UTF8, $this->CharSet);
+ //Ignore IDE complaints about this line - method signature changed in PHP 5.4
+ $errorcode = 0;
+ if (defined('INTL_IDNA_VARIANT_UTS46')) {
+ //Use the current punycode standard (appeared in PHP 7.2)
+ $punycode = idn_to_ascii(
+ $domain,
+ \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI |
+ \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII,
+ \INTL_IDNA_VARIANT_UTS46
+ );
+ } elseif (defined('INTL_IDNA_VARIANT_2003')) {
+ //Fall back to this old, deprecated/removed encoding
+ $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_2003);
+ } else {
+ //Fall back to a default we don't know about
+ $punycode = idn_to_ascii($domain, $errorcode);
+ }
+ if (false !== $punycode) {
+ return substr($address, 0, $pos) . $punycode;
+ }
+ }
+ }
+
+ return $address;
+ }
+
+ /**
+ * Create a message and send it.
+ * Uses the sending method specified by $Mailer.
+ *
+ * @throws Exception
+ *
+ * @return bool false on error - See the ErrorInfo property for details of the error
+ */
+ public function send()
+ {
+ try {
+ if (!$this->preSend()) {
+ return false;
+ }
+
+ return $this->postSend();
+ } catch (Exception $exc) {
+ $this->mailHeader = '';
+ $this->setError($exc->getMessage());
+ if ($this->exceptions) {
+ throw $exc;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Prepare a message for sending.
+ *
+ * @throws Exception
+ *
+ * @return bool
+ */
+ public function preSend()
+ {
+ if (
+ 'smtp' === $this->Mailer
+ || ('mail' === $this->Mailer && (\PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
+ ) {
+ //SMTP mandates RFC-compliant line endings
+ //and it's also used with mail() on Windows
+ static::setLE(self::CRLF);
+ } else {
+ //Maintain backward compatibility with legacy Linux command line mailers
+ static::setLE(PHP_EOL);
+ }
+ //Check for buggy PHP versions that add a header with an incorrect line break
+ if (
+ 'mail' === $this->Mailer
+ && ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017)
+ || (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103))
+ && ini_get('mail.add_x_header') === '1'
+ && stripos(PHP_OS, 'WIN') === 0
+ ) {
+ trigger_error($this->lang('buggy_php'), E_USER_WARNING);
+ }
+
+ try {
+ $this->error_count = 0; //Reset errors
+ $this->mailHeader = '';
+
+ //Dequeue recipient and Reply-To addresses with IDN
+ foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
+ $params[1] = $this->punyencodeAddress($params[1]);
+ call_user_func_array([$this, 'addAnAddress'], $params);
+ }
+ if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
+ throw new Exception($this->lang('provide_address'), self::STOP_CRITICAL);
+ }
+
+ //Validate From, Sender, and ConfirmReadingTo addresses
+ foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
+ $this->$address_kind = trim($this->$address_kind);
+ if (empty($this->$address_kind)) {
+ continue;
+ }
+ $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
+ if (!static::validateAddress($this->$address_kind)) {
+ $error_message = sprintf(
+ '%s (%s): %s',
+ $this->lang('invalid_address'),
+ $address_kind,
+ $this->$address_kind
+ );
+ $this->setError($error_message);
+ $this->edebug($error_message);
+ if ($this->exceptions) {
+ throw new Exception($error_message);
+ }
+
+ return false;
+ }
+ }
+
+ //Set whether the message is multipart/alternative
+ if ($this->alternativeExists()) {
+ $this->ContentType = static::CONTENT_TYPE_MULTIPART_ALTERNATIVE;
+ }
+
+ $this->setMessageType();
+ //Refuse to send an empty message unless we are specifically allowing it
+ if (!$this->AllowEmpty && empty($this->Body)) {
+ throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
+ }
+
+ //Trim subject consistently
+ $this->Subject = trim($this->Subject);
+ //Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
+ $this->MIMEHeader = '';
+ $this->MIMEBody = $this->createBody();
+ //createBody may have added some headers, so retain them
+ $tempheaders = $this->MIMEHeader;
+ $this->MIMEHeader = $this->createHeader();
+ $this->MIMEHeader .= $tempheaders;
+
+ //To capture the complete message when using mail(), create
+ //an extra header list which createHeader() doesn't fold in
+ if ('mail' === $this->Mailer) {
+ if (count($this->to) > 0) {
+ $this->mailHeader .= $this->addrAppend('To', $this->to);
+ } else {
+ $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
+ }
+ $this->mailHeader .= $this->headerLine(
+ 'Subject',
+ $this->encodeHeader($this->secureHeader($this->Subject))
+ );
+ }
+
+ //Sign with DKIM if enabled
+ if (
+ !empty($this->DKIM_domain)
+ && !empty($this->DKIM_selector)
+ && (!empty($this->DKIM_private_string)
+ || (!empty($this->DKIM_private)
+ && static::isPermittedPath($this->DKIM_private)
+ && file_exists($this->DKIM_private)
+ )
+ )
+ ) {
+ $header_dkim = $this->DKIM_Add(
+ $this->MIMEHeader . $this->mailHeader,
+ $this->encodeHeader($this->secureHeader($this->Subject)),
+ $this->MIMEBody
+ );
+ $this->MIMEHeader = static::stripTrailingWSP($this->MIMEHeader) . static::$LE .
+ static::normalizeBreaks($header_dkim) . static::$LE;
+ }
+
+ return true;
+ } catch (Exception $exc) {
+ $this->setError($exc->getMessage());
+ if ($this->exceptions) {
+ throw $exc;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Actually send a message via the selected mechanism.
+ *
+ * @throws Exception
+ *
+ * @return bool
+ */
+ public function postSend()
+ {
+ try {
+ //Choose the mailer and send through it
+ switch ($this->Mailer) {
+ case 'sendmail':
+ case 'qmail':
+ return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
+ case 'smtp':
+ return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
+ case 'mail':
+ return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
+ default:
+ $sendMethod = $this->Mailer . 'Send';
+ if (method_exists($this, $sendMethod)) {
+ return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
+ }
+
+ 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->exceptions) {
+ throw $exc;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Send mail using the $Sendmail program.
+ *
+ * @see PHPMailer::$Sendmail
+ *
+ * @param string $header The message headers
+ * @param string $body The message body
+ *
+ * @throws Exception
+ *
+ * @return bool
+ */
+ protected function sendmailSend($header, $body)
+ {
+ if ($this->Mailer === 'qmail') {
+ $this->edebug('Sending with qmail');
+ } else {
+ $this->edebug('Sending with sendmail');
+ }
+ $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
+ //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
+ //A space after `-f` is optional, but there is a long history of its presence
+ //causing problems, so we don't use one
+ //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
+ //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
+ //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
+ //Example problem: https://www.drupal.org/node/1057954
+
+ //PHP 5.6 workaround
+ $sendmail_from_value = ini_get('sendmail_from');
+ if (empty($this->Sender) && !empty($sendmail_from_value)) {
+ //PHP config has a sender address we can use
+ $this->Sender = ini_get('sendmail_from');
+ }
+ //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+ if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
+ if ($this->Mailer === 'qmail') {
+ $sendmailFmt = '%s -f%s';
+ } else {
+ $sendmailFmt = '%s -oi -f%s -t';
+ }
+ } else {
+ //allow sendmail to choose a default envelope sender. It may
+ //seem preferable to force it to use the From header as with
+ //SMTP, but that introduces new problems (see
+ //), and
+ //it has historically worked this way.
+ $sendmailFmt = '%s -oi -t';
+ }
+
+ $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
+ $this->edebug('Sendmail path: ' . $this->Sendmail);
+ $this->edebug('Sendmail command: ' . $sendmail);
+ $this->edebug('Envelope sender: ' . $this->Sender);
+ $this->edebug("Headers: {$header}");
+
+ if ($this->SingleTo) {
+ foreach ($this->SingleToArray as $toAddr) {
+ $mail = @popen($sendmail, 'w');
+ if (!$mail) {
+ throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+ }
+ $this->edebug("To: {$toAddr}");
+ fwrite($mail, 'To: ' . $toAddr . "\n");
+ fwrite($mail, $header);
+ fwrite($mail, $body);
+ $result = pclose($mail);
+ $addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
+ $this->doCallback(
+ ($result === 0),
+ [[$addrinfo['address'], $addrinfo['name']]],
+ $this->cc,
+ $this->bcc,
+ $this->Subject,
+ $body,
+ $this->From,
+ []
+ );
+ $this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
+ if (0 !== $result) {
+ throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+ }
+ }
+ } else {
+ $mail = @popen($sendmail, 'w');
+ if (!$mail) {
+ throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+ }
+ fwrite($mail, $header);
+ fwrite($mail, $body);
+ $result = pclose($mail);
+ $this->doCallback(
+ ($result === 0),
+ $this->to,
+ $this->cc,
+ $this->bcc,
+ $this->Subject,
+ $body,
+ $this->From,
+ []
+ );
+ $this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
+ if (0 !== $result) {
+ throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
+ * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
+ *
+ * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
+ *
+ * @param string $string The string to be validated
+ *
+ * @return bool
+ */
+ protected static function isShellSafe($string)
+ {
+ //It's not possible to use shell commands safely (which includes the mail() function) without escapeshellarg,
+ //but some hosting providers disable it, creating a security problem that we don't want to have to deal with,
+ //so we don't.
+ if (!function_exists('escapeshellarg') || !function_exists('escapeshellcmd')) {
+ return false;
+ }
+
+ if (
+ escapeshellcmd($string) !== $string
+ || !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])
+ ) {
+ return false;
+ }
+
+ $length = strlen($string);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $c = $string[$i];
+
+ //All other characters have a special meaning in at least one common shell, including = and +.
+ //Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
+ //Note that this does permit non-Latin alphanumeric characters based on the current locale.
+ if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check whether a file path is of a permitted type.
+ * Used to reject URLs and phar files from functions that access local file paths,
+ * such as addAttachment.
+ *
+ * @param string $path A relative or absolute path to a file
+ *
+ * @return bool
+ */
+ protected static function isPermittedPath($path)
+ {
+ //Matches scheme definition from https://tools.ietf.org/html/rfc3986#section-3.1
+ return !preg_match('#^[a-z][a-z\d+.-]*://#i', $path);
+ }
+
+ /**
+ * Check whether a file path is safe, accessible, and readable.
+ *
+ * @param string $path A relative or absolute path to a file
+ *
+ * @return bool
+ */
+ protected static function fileIsAccessible($path)
+ {
+ if (!static::isPermittedPath($path)) {
+ return false;
+ }
+ $readable = file_exists($path);
+ //If not a UNC path (expected to start with \\), check read permission, see #2069
+ if (strpos($path, '\\\\') !== 0) {
+ $readable = $readable && is_readable($path);
+ }
+ return $readable;
+ }
+
+ /**
+ * Send mail using the PHP mail() function.
+ *
+ * @see http://www.php.net/manual/en/book.mail.php
+ *
+ * @param string $header The message headers
+ * @param string $body The message body
+ *
+ * @throws Exception
+ *
+ * @return bool
+ */
+ protected function mailSend($header, $body)
+ {
+ $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
+
+ $toArr = [];
+ foreach ($this->to as $toaddr) {
+ $toArr[] = $this->addrFormat($toaddr);
+ }
+ $to = implode(', ', $toArr);
+
+ $params = null;
+ //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
+ //A space after `-f` is optional, but there is a long history of its presence
+ //causing problems, so we don't use one
+ //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
+ //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
+ //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
+ //Example problem: https://www.drupal.org/node/1057954
+ //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+
+ //PHP 5.6 workaround
+ $sendmail_from_value = ini_get('sendmail_from');
+ if (empty($this->Sender) && !empty($sendmail_from_value)) {
+ //PHP config has a sender address we can use
+ $this->Sender = ini_get('sendmail_from');
+ }
+ if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
+ if (self::isShellSafe($this->Sender)) {
+ $params = sprintf('-f%s', $this->Sender);
+ }
+ $old_from = ini_get('sendmail_from');
+ ini_set('sendmail_from', $this->Sender);
+ }
+ $result = false;
+ if ($this->SingleTo && count($toArr) > 1) {
+ foreach ($toArr as $toAddr) {
+ $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
+ $addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
+ $this->doCallback(
+ $result,
+ [[$addrinfo['address'], $addrinfo['name']]],
+ $this->cc,
+ $this->bcc,
+ $this->Subject,
+ $body,
+ $this->From,
+ []
+ );
+ }
+ } else {
+ $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
+ $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
+ }
+ if (isset($old_from)) {
+ ini_set('sendmail_from', $old_from);
+ }
+ if (!$result) {
+ throw new Exception($this->lang('instantiate'), self::STOP_CRITICAL);
+ }
+
+ return true;
+ }
+
+ /**
+ * Get an instance to use for SMTP operations.
+ * Override this function to load your own SMTP implementation,
+ * or set one with setSMTPInstance.
+ *
+ * @return SMTP
+ */
+ public function getSMTPInstance()
+ {
+ if (!is_object($this->smtp)) {
+ $this->smtp = new SMTP();
+ }
+
+ return $this->smtp;
+ }
+
+ /**
+ * Provide an instance to use for SMTP operations.
+ *
+ * @return SMTP
+ */
+ public function setSMTPInstance(SMTP $smtp)
+ {
+ $this->smtp = $smtp;
+
+ return $this->smtp;
+ }
+
+ /**
+ * Send mail via SMTP.
+ * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
+ *
+ * @see PHPMailer::setSMTPInstance() to use a different class.
+ *
+ * @uses \PHPMailer\PHPMailer\SMTP
+ *
+ * @param string $header The message headers
+ * @param string $body The message body
+ *
+ * @throws Exception
+ *
+ * @return bool
+ */
+ protected function smtpSend($header, $body)
+ {
+ $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
+ $bad_rcpt = [];
+ if (!$this->smtpConnect($this->SMTPOptions)) {
+ throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
+ }
+ //Sender already validated in preSend()
+ if ('' === $this->Sender) {
+ $smtp_from = $this->From;
+ } else {
+ $smtp_from = $this->Sender;
+ }
+ if (!$this->smtp->mail($smtp_from)) {
+ $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
+ throw new Exception($this->ErrorInfo, self::STOP_CRITICAL);
+ }
+
+ $callbacks = [];
+ //Attempt to send to all recipients
+ foreach ([$this->to, $this->cc, $this->bcc] as $togroup) {
+ foreach ($togroup as $to) {
+ if (!$this->smtp->recipient($to[0], $this->dsn)) {
+ $error = $this->smtp->getError();
+ $bad_rcpt[] = ['to' => $to[0], 'error' => $error['detail']];
+ $isSent = false;
+ } else {
+ $isSent = true;
+ }
+
+ $callbacks[] = ['issent' => $isSent, 'to' => $to[0], 'name' => $to[1]];
+ }
+ }
+
+ //Only send the DATA command if we have viable recipients
+ if ((count($this->all_recipients) > count($bad_rcpt)) && !$this->smtp->data($header . $body)) {
+ throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
+ }
+
+ $smtp_transaction_id = $this->smtp->getLastTransactionID();
+
+ if ($this->SMTPKeepAlive) {
+ $this->smtp->reset();
+ } else {
+ $this->smtp->quit();
+ $this->smtp->close();
+ }
+
+ foreach ($callbacks as $cb) {
+ $this->doCallback(
+ $cb['issent'],
+ [[$cb['to'], $cb['name']]],
+ [],
+ [],
+ $this->Subject,
+ $body,
+ $this->From,
+ ['smtp_transaction_id' => $smtp_transaction_id]
+ );
+ }
+
+ //Create error message for any bad addresses
+ if (count($bad_rcpt) > 0) {
+ $errstr = '';
+ foreach ($bad_rcpt as $bad) {
+ $errstr .= $bad['to'] . ': ' . $bad['error'];
+ }
+ throw new Exception($this->lang('recipients_failed') . $errstr, self::STOP_CONTINUE);
+ }
+
+ return true;
+ }
+
+ /**
+ * Initiate a connection to an SMTP server.
+ * Returns false if the operation failed.
+ *
+ * @param array $options An array of options compatible with stream_context_create()
+ *
+ * @throws Exception
+ *
+ * @uses \PHPMailer\PHPMailer\SMTP
+ *
+ * @return bool
+ */
+ public function smtpConnect($options = null)
+ {
+ if (null === $this->smtp) {
+ $this->smtp = $this->getSMTPInstance();
+ }
+
+ //If no options are provided, use whatever is set in the instance
+ if (null === $options) {
+ $options = $this->SMTPOptions;
+ }
+
+ //Already connected?
+ if ($this->smtp->connected()) {
+ return true;
+ }
+
+ $this->smtp->setTimeout($this->Timeout);
+ $this->smtp->setDebugLevel($this->SMTPDebug);
+ $this->smtp->setDebugOutput($this->Debugoutput);
+ $this->smtp->setVerp($this->do_verp);
+ $hosts = explode(';', $this->Host);
+ $lastexception = null;
+
+ foreach ($hosts as $hostentry) {
+ $hostinfo = [];
+ if (
+ !preg_match(
+ '/^(?:(ssl|tls):\/\/)?(.+?)(?::(\d+))?$/',
+ trim($hostentry),
+ $hostinfo
+ )
+ ) {
+ $this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
+ //Not a valid host entry
+ continue;
+ }
+ //$hostinfo[1]: optional ssl or tls prefix
+ //$hostinfo[2]: the hostname
+ //$hostinfo[3]: optional port number
+ //The host string prefix can temporarily override the current setting for SMTPSecure
+ //If it's not specified, the default value is used
+
+ //Check the host name is a valid name or IP address before trying to use it
+ if (!static::isValidHost($hostinfo[2])) {
+ $this->edebug($this->lang('invalid_host') . ' ' . $hostinfo[2]);
+ continue;
+ }
+ $prefix = '';
+ $secure = $this->SMTPSecure;
+ $tls = (static::ENCRYPTION_STARTTLS === $this->SMTPSecure);
+ if ('ssl' === $hostinfo[1] || ('' === $hostinfo[1] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
+ $prefix = 'ssl://';
+ $tls = false; //Can't have SSL and TLS at the same time
+ $secure = static::ENCRYPTION_SMTPS;
+ } elseif ('tls' === $hostinfo[1]) {
+ $tls = true;
+ //TLS doesn't use a prefix
+ $secure = static::ENCRYPTION_STARTTLS;
+ }
+ //Do we need the OpenSSL extension?
+ $sslext = defined('OPENSSL_ALGO_SHA256');
+ if (static::ENCRYPTION_STARTTLS === $secure || static::ENCRYPTION_SMTPS === $secure) {
+ //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
+ if (!$sslext) {
+ throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
+ }
+ }
+ $host = $hostinfo[2];
+ $port = $this->Port;
+ if (
+ array_key_exists(3, $hostinfo) &&
+ is_numeric($hostinfo[3]) &&
+ $hostinfo[3] > 0 &&
+ $hostinfo[3] < 65536
+ ) {
+ $port = (int) $hostinfo[3];
+ }
+ if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
+ try {
+ if ($this->Helo) {
+ $hello = $this->Helo;
+ } else {
+ $hello = $this->serverHostname();
+ }
+ $this->smtp->hello($hello);
+ //Automatically enable TLS encryption if:
+ //* it's not disabled
+ //* we have openssl extension
+ //* we are not already using SSL
+ //* the server offers STARTTLS
+ if ($this->SMTPAutoTLS && $sslext && 'ssl' !== $secure && $this->smtp->getServerExt('STARTTLS')) {
+ $tls = true;
+ }
+ if ($tls) {
+ if (!$this->smtp->startTLS()) {
+ $message = $this->getSmtpErrorMessage('connect_host');
+ throw new Exception($message);
+ }
+ //We must resend EHLO after TLS negotiation
+ $this->smtp->hello($hello);
+ }
+ if (
+ $this->SMTPAuth && !$this->smtp->authenticate(
+ $this->Username,
+ $this->Password,
+ $this->AuthType,
+ $this->oauth
+ )
+ ) {
+ throw new Exception($this->lang('authenticate'));
+ }
+
+ return true;
+ } catch (Exception $exc) {
+ $lastexception = $exc;
+ $this->edebug($exc->getMessage());
+ //We must have connected, but then failed TLS or Auth, so close connection nicely
+ $this->smtp->quit();
+ }
+ }
+ }
+ //If we get here, all connection attempts have failed, so close connection hard
+ $this->smtp->close();
+ //As we've caught all exceptions, just report whatever the last one was
+ if ($this->exceptions && null !== $lastexception) {
+ throw $lastexception;
+ } elseif ($this->exceptions) {
+ // no exception was thrown, likely $this->smtp->connect() failed
+ $message = $this->getSmtpErrorMessage('connect_host');
+ throw new Exception($message);
+ }
+
+ return false;
+ }
+
+ /**
+ * Close the active SMTP session if one exists.
+ */
+ public function smtpClose()
+ {
+ if ((null !== $this->smtp) && $this->smtp->connected()) {
+ $this->smtp->quit();
+ $this->smtp->close();
+ }
+ }
+
+ /**
+ * Set the language for error messages.
+ * The default language is English.
+ *
+ * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
+ * Optionally, the language code can be enhanced with a 4-character
+ * script annotation and/or a 2-character country annotation.
+ * @param string $lang_path Path to the language file directory, with trailing separator (slash)
+ * Do not set this from user input!
+ *
+ * @return bool Returns true if the requested language was loaded, false otherwise.
+ */
+ public function setLanguage($langcode = 'en', $lang_path = '')
+ {
+ //Backwards compatibility for renamed language codes
+ $renamed_langcodes = [
+ 'br' => 'pt_br',
+ 'cz' => 'cs',
+ 'dk' => 'da',
+ 'no' => 'nb',
+ 'se' => 'sv',
+ 'rs' => 'sr',
+ 'tg' => 'tl',
+ 'am' => 'hy',
+ ];
+
+ if (array_key_exists($langcode, $renamed_langcodes)) {
+ $langcode = $renamed_langcodes[$langcode];
+ }
+
+ //Define full set of translatable strings in English
+ $PHPMAILER_LANG = [
+ 'authenticate' => 'SMTP Error: Could not authenticate.',
+ 'buggy_php' => 'Your version of PHP is affected by a bug that may result in corrupted messages.' .
+ ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' .
+ ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.',
+ 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
+ 'data_not_accepted' => 'SMTP Error: data not accepted.',
+ 'empty_message' => 'Message body empty',
+ 'encoding' => 'Unknown encoding: ',
+ 'execute' => 'Could not execute: ',
+ 'extension_missing' => 'Extension missing: ',
+ 'file_access' => 'Could not access file: ',
+ 'file_open' => 'File Error: Could not open file: ',
+ 'from_failed' => 'The following From address failed: ',
+ 'instantiate' => 'Could not instantiate mail function.',
+ 'invalid_address' => 'Invalid address: ',
+ 'invalid_header' => 'Invalid header name or value',
+ 'invalid_hostentry' => 'Invalid hostentry: ',
+ 'invalid_host' => 'Invalid host: ',
+ 'mailer_not_supported' => ' mailer is not supported.',
+ 'provide_address' => 'You must provide at least one recipient email address.',
+ 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
+ 'signing' => 'Signing Error: ',
+ 'smtp_code' => 'SMTP code: ',
+ 'smtp_code_ex' => 'Additional SMTP info: ',
+ 'smtp_connect_failed' => 'SMTP connect() failed.',
+ 'smtp_detail' => 'Detail: ',
+ 'smtp_error' => 'SMTP server error: ',
+ 'variable_set' => 'Cannot set or reset variable: ',
+ ];
+ if (empty($lang_path)) {
+ //Calculate an absolute path so it can work if CWD is not here
+ $lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
+ }
+
+ //Validate $langcode
+ $foundlang = true;
+ $langcode = strtolower($langcode);
+ if (
+ !preg_match('/^(?P[a-z]{2})(?P