init: 项目初始代码
This commit is contained in:
101
extend/apiRes/Api.php
Normal file
101
extend/apiRes/Api.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
namespace apiRes;
|
||||
|
||||
class Api
|
||||
{
|
||||
private static $response;
|
||||
private $state = [];
|
||||
|
||||
private $default_states = [
|
||||
'success' => [
|
||||
'errno' => 0,
|
||||
'errmsg' => '操作成功!',
|
||||
'data' => []
|
||||
],
|
||||
'error' => [
|
||||
'errno' => 2001,
|
||||
'errmsg' => '操作错误!',
|
||||
'data' => []
|
||||
],
|
||||
'NoData' => [
|
||||
'errno' => 2002,
|
||||
'errmsg' => '没有数据!',
|
||||
'data' => []
|
||||
],
|
||||
'NotLoggedIn' => [
|
||||
'errno' => 2003,
|
||||
'errmsg' => '未登录',
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
|
||||
private function __construct($erro)
|
||||
{
|
||||
isset($erro) || die('请确认返回类型!');
|
||||
$this->state = $this->default_states[$erro];
|
||||
return $this;
|
||||
}
|
||||
|
||||
// 单例
|
||||
public static function result($erro)
|
||||
{
|
||||
if (!self::$response) {
|
||||
self::$response = new self($erro);
|
||||
}
|
||||
return self::$response;
|
||||
}
|
||||
|
||||
// 返回错误
|
||||
public static function error($msg='', $data=[], $to_array=false)
|
||||
{
|
||||
$ins = self::result('error');
|
||||
if ($msg) {
|
||||
$ins = $ins->message($msg);
|
||||
}
|
||||
|
||||
return $ins->response($data, $to_array);
|
||||
}
|
||||
|
||||
// 返回成功
|
||||
public static function success($msg='', $data=[], $to_array=false)
|
||||
{
|
||||
$ins = self::result('success');
|
||||
if ($msg) {
|
||||
$ins = $ins->message($msg);
|
||||
}
|
||||
|
||||
return $ins->response($data, $to_array);
|
||||
}
|
||||
|
||||
// 写入返回信息
|
||||
public function message($message='')
|
||||
{
|
||||
$message ? $this->state['errmsg'] = $message : '';
|
||||
return $this;
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
public function response($data=[], $to_array=false)
|
||||
{
|
||||
if (!empty($data)) {
|
||||
$this->state['data'] = $data;
|
||||
}
|
||||
if (request()->isJson() || $to_array) {
|
||||
$output = $this->state;
|
||||
} else {
|
||||
$output = json_encode($this->state, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转成数组
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
if (is_array($this->state)) {
|
||||
return $this->state;
|
||||
}
|
||||
return json_decode($this->state, true);
|
||||
}
|
||||
}
|
||||
292
extend/encryption/Rsa.php
Normal file
292
extend/encryption/Rsa.php
Normal file
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
namespace encryption;
|
||||
|
||||
class Rsa
|
||||
{
|
||||
const SIGN_CERT_PWD = '123456'; // 签名证书密码
|
||||
private $public_key; // 公钥
|
||||
private $private_key; // 私钥
|
||||
private $cert_save_path = ''; // 证书文件保存目录
|
||||
private $openssl_cnf_path = '/etc/ssl/openssl.cnf';
|
||||
protected static $rsa;
|
||||
|
||||
/**
|
||||
* 设私有构造方法防止对象被new
|
||||
*/
|
||||
private function __construct($config)
|
||||
{
|
||||
if ($config['public'] && $config['private']) {
|
||||
if (is_file($config['public'])) {
|
||||
$this->public_key = $this->getPublicKey($config['public']);
|
||||
} else {
|
||||
$this->public_key = openssl_pkey_get_public($config['public']);
|
||||
if (!$this->public_key) {
|
||||
die('请检查公钥是否正确');
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file($config['private'])) {
|
||||
$this->private_key = $this->getPrivateKey($config['private']);
|
||||
} else {
|
||||
$this->private_key = openssl_pkey_get_private($config['private']);
|
||||
if (!$this->private_key) {
|
||||
die('请检查私钥是否正确');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($config['cert_save_path']) $this->cert_save_path = $config['cert_save_path'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例获取对象实例
|
||||
*/
|
||||
public static function instance($config=array())
|
||||
{
|
||||
if (!self::$rsa) {
|
||||
if (empty($config)) {
|
||||
$config = [
|
||||
'public' => '',
|
||||
'private' => '',
|
||||
'cert_save_path' => ''
|
||||
];
|
||||
}
|
||||
self::$rsa = new self($config);
|
||||
}
|
||||
return self::$rsa;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件
|
||||
*/
|
||||
private function fileGet($file)
|
||||
{
|
||||
if (!file_exists($file)) {
|
||||
die($file . "不是文件");
|
||||
}
|
||||
return file_get_contents($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公钥
|
||||
*/
|
||||
private function getPublicKey($path)
|
||||
{
|
||||
$pubKey = $this->fileGet($path);
|
||||
if (!$pubKey) {
|
||||
die('请检查公钥路径是否正确');
|
||||
}
|
||||
return openssl_pkey_get_public($pubKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取私钥
|
||||
*/
|
||||
private function getPrivateKey($path)
|
||||
{
|
||||
$priKey = $this->fileGet($path);
|
||||
if (!$priKey) {
|
||||
die('请检查私钥路径是否正确');
|
||||
}
|
||||
return openssl_pkey_get_private($priKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用私钥生成签名
|
||||
* @param string 用于生成签名的字符串
|
||||
* @return string 签名后的值
|
||||
*/
|
||||
public function signPrivate($data)
|
||||
{
|
||||
$signature = false;
|
||||
if (openssl_sign($data, $signature, $this->private_key)) {
|
||||
$signature = base64_encode($signature);
|
||||
}
|
||||
return $signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥验签
|
||||
* @param $data = array('data'='','signature'='')
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyPublic($data)
|
||||
{
|
||||
$bool = false;
|
||||
if (!$data['data'] || !$data['signature']) {
|
||||
die('数据源或签名值为出错!');
|
||||
}
|
||||
$result = base64_decode($data['signature']);
|
||||
switch (openssl_verify($data['data'], $result, $this->public_key)) {
|
||||
case 1:
|
||||
$bool = true;
|
||||
break;
|
||||
case 0:
|
||||
case -1:
|
||||
$bool = false;
|
||||
break;
|
||||
default:
|
||||
$bool = false;
|
||||
}
|
||||
return $bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥加密
|
||||
*/
|
||||
public function encryptPublic($data)
|
||||
{
|
||||
$crypted = false;
|
||||
if (is_array($data)) {
|
||||
$data = json_encode($data);
|
||||
}
|
||||
$cryp = strrev($data); // 将数据前后反转再加密
|
||||
if (openssl_public_encrypt($cryp, $crypted, $this->public_key, OPENSSL_PKCS1_PADDING)) {
|
||||
$crypted = base64_encode($crypted);
|
||||
}
|
||||
return $crypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥分块加密
|
||||
*/
|
||||
public function chunkEncryptPublic($data, $limit = 117)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
$data = json_encode($data);
|
||||
}
|
||||
$datas = str_split($data, $limit);
|
||||
|
||||
$crypteds = [];
|
||||
foreach ($datas as $key => $val) {
|
||||
$crypteds[$key] = $this->encryptPublic($val);
|
||||
}
|
||||
return $crypteds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用私钥解密
|
||||
*/
|
||||
public function decryptPrivate($encrypted)
|
||||
{
|
||||
$decrypted = '';
|
||||
$data = base64_decode($encrypted);
|
||||
if (openssl_private_decrypt($data, $decrypted, $this->private_key, OPENSSL_PKCS1_PADDING)) {
|
||||
$decrypted = rtrim(strrev($decrypted), '\0');
|
||||
}
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用私钥分块解密
|
||||
*/
|
||||
public function chunkDecryptPrivate($encrypteds)
|
||||
{
|
||||
$decrypted = '';
|
||||
$encrypteds = htmlspecialchars_decode($encrypteds);
|
||||
if (!is_array($encrypteds)) {
|
||||
$arr = explode(',', $encrypteds);
|
||||
if ($arr) {
|
||||
$encrypteds = $arr;
|
||||
} else {
|
||||
return json_decode($this->decryptPrivate($encrypteds));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($encrypteds as $key => $val) {
|
||||
$decrypted .= $this->decryptPrivate($val);
|
||||
}
|
||||
|
||||
$res = json_decode($decrypted, true);
|
||||
if (is_array($res)) return $res;
|
||||
return json_decode($res, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成公私钥
|
||||
*/
|
||||
public function createRsa($writeFile=false)
|
||||
{
|
||||
$config = array("config" => $this->openssl_cnf_path);
|
||||
|
||||
// 生成公私钥
|
||||
$privkey = openssl_pkey_new($config);
|
||||
openssl_pkey_export($privkey, $private_key, null, $config); // 导出私钥$private_key
|
||||
$public_key = openssl_pkey_get_details($privkey); // 导出公钥$public_key
|
||||
|
||||
if (!$writeFile) {
|
||||
return array('private_key' => $private_key, 'public_key' => $public_key['key']);
|
||||
}
|
||||
|
||||
$publicPath = $this->cert_save_path . "rsa_public_key.pem"; // 生成公钥路径
|
||||
$privatePath = $this->cert_save_path . "rsa_private_key.pem"; // 私钥文件路径
|
||||
|
||||
// 生成公钥文件
|
||||
if (!is_writeable($publicPath)) {
|
||||
chmod($publicPath, 0755);
|
||||
}
|
||||
$fp = fopen($publicPath, "w");
|
||||
fwrite($fp, $public_key['key']);
|
||||
fclose($fp);
|
||||
// 生成私钥文件
|
||||
if (!is_writeable($privatePath)) {
|
||||
chmod($privatePath, 0755);
|
||||
}
|
||||
$fp = fopen($privatePath, "w");
|
||||
fwrite($fp, $private_key);
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成证书和密钥
|
||||
*/
|
||||
public function createCsr($writeFile=false)
|
||||
{
|
||||
$dn = array(
|
||||
"countryName" => 'CN', // 所在国家名称
|
||||
"stateOrProvinceName" => 'Hunan', // 所在省份名称
|
||||
"localityName" => 'Changsha', // 所在城市名称
|
||||
"organizationName" => 'opd', // 注册人姓名
|
||||
"organizationalUnitName" => 'orico_opd', // 组织名称
|
||||
"commonName" => 'orico_opd', // 公共名称
|
||||
"emailAddress" => '735273025@qq.com' // 邮箱
|
||||
);
|
||||
|
||||
$privkeypass = self::SIGN_CERT_PWD; //私钥密码
|
||||
$config = array(
|
||||
"config" => $this->openssl_cnf_path,
|
||||
"digest_alg" => "sha1",
|
||||
"private_key_bits" => 2048,
|
||||
"private_key_type" => OPENSSL_KEYTYPE_DSA,
|
||||
"encrypt_key" => false
|
||||
);
|
||||
|
||||
$privkey = openssl_pkey_new($config);
|
||||
$csr = openssl_csr_new($dn, $privkey, $config);
|
||||
$sscert = openssl_csr_sign($csr, null, $privkey, 365, $config);
|
||||
openssl_x509_export($sscert, $csrkey); // 导出证书$csrkey
|
||||
openssl_pkcs12_export($sscert, $private_key, $privkey, $privkeypass); // 导出密钥$private_key
|
||||
|
||||
if (!$writeFile) {
|
||||
return array('csrkey' => $csrkey, 'private_key_pfx' => $private_key);
|
||||
}
|
||||
|
||||
$cerpath = $this->cert_save_path . "csrkey.cer"; // 生成证书路径
|
||||
$pfxpath = $this->cert_save_path . "private_key.pfx"; // 密钥文件路径
|
||||
|
||||
// 生成证书文件
|
||||
if (!is_writeable($cerpath)) {
|
||||
chmod($cerpath, 0755);
|
||||
}
|
||||
$fp = fopen($cerpath, "w");
|
||||
fwrite($fp, $csrkey);
|
||||
fclose($fp);
|
||||
// 生成密钥文件
|
||||
if (!is_writeable($pfxpath)) {
|
||||
chmod($pfxpath, 0755);
|
||||
}
|
||||
$fp = fopen($pfxpath, "w");
|
||||
fwrite($fp, $private_key);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
0
extend/encryption/cert/csrkey.cer
Normal file
0
extend/encryption/cert/csrkey.cer
Normal file
0
extend/encryption/cert/private_key.pfx
Normal file
0
extend/encryption/cert/private_key.pfx
Normal file
3
extend/encryption/cert/rsa_private_key.pem
Normal file
3
extend/encryption/cert/rsa_private_key.pem
Normal file
@@ -0,0 +1,3 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCb4X1wN9ret271gWrsXlSymFinlheMUz2kIsyKREtlfE7ajH6Bm5bEFxe/HnCDxh37ekUJq4JMeU1awJgYA4mlvaQ67DSf4/AZWk2Dg8TLQaE7VeBJoPadDyciIwuFhcWB2lfD62KRlbXqgjfji7IjZE4ysVB99DofpJ9c9xd0NtzzuBNjgxh+f6BsegsIkqLIpKGIONePrY9cCj+vOMaRdUgWczQOftWXtJXiRz5kUxwV6CSQQbbPFEySStlW2WMBF15FyeOTXERvpgOoP4O+j/0GMW3R+4dKUxFY+SPrmMMB6HmJgySgCIVuwlUJyLlmhZuaIumryyJ19Yc+jB0ZAgMBAAECggEAA82hoN5MAckZ9PV+ZVv71wuuhhA8bNkPFPUgZnM6H7TDu8NXxtPD/u7NToVwm1Z3Hs6h5pV/rVv8Ti2KyHM1pYyV+DYRJqGKFyRD5eSOJaNpSqhSu5koyzY2bzfJrS1RX1SzdX1Fv2WWta0NrgiXhROKcOQwoZIW5PTASqVgth4iztEmseuU9pgh/dnMOXCLGmGB26Z2HTnuV0tHC4/goMmsi0eGOy40VEBxPL0JJegWM+teRSbSWGzOfTu95wnpIr66FT0aOVdHVuhMTYYHUfbEh/lnCZExfqjNfEVuSLB+jHBeLfFXdg3TY/svVizXJ4SvzI1EzM6Y145zMTdk8QKBgQDPKT1BQHWIPyXs3IzqDpmP9koBOm03rZZ46CneGLFj9vRAeK9awAto6aqH/WHLb48fSK5LQteWf+rvRiqoPjansoFvzh1dgk+0FON1jUNk4LlwOVEL38WhD98cJ/SwOVdwsYfYySb2pwcZ3K4gdTmax264XFRNGU8Ar4l17NHVtQKBgQDAoVcyWHtpJ6Pk4CuOSWt1S5y1km1dAudJfRAyYlk+9G6Qq1zSoScio/1T/TAS58KHcoSV0SmGu9heF2p02ov4MzsFr//cnBh2Y3aiTnvnyxehp5V0M9CLy524gHDANHO3BxCjlV6tMFqvUuhJfurN36KarYvLJjGU3MoWLPiIVQKBgQCfuWozP2HfdODm6X30kOExsHGK1OOUxFB6VHbDeUJ8ktHsS6DYVa32bANB6slWM2OkeUN5X8Ydke8wIWeOZLl7PxSxgbf+exS9AkYGQq6tvt77ehXVE+mqrzQU33G31d5nU1oseZuDHXFKLW5MNFX/0ri5iOaus07Ido+Dzt5S6QKBgQCef+MEnQOmyaQ0vjN4l3bhA79FM9/i6XGv6UT7gCsY/v0+8pGlCk7uVOssQadd1u8cjiEEOR+nKkdlXHUPA4iqSFUnX+Ly/kmumDbUZCnV1ylxrTfvbncJoBf96UldDYutLRYG0/AcJy5nFpvlZZYEoh/kkCn3lUy0xVtPFd/GJQKBgQCDfPkSHDxyeSZQ2xlj+4xqIGfGLbK/ijO9AuC7rSnWE2bYD1cseItVK6O0nZ0Gw4vmmvHDF9Z6yxCobIzyf6fUExvVRm3oMwjSrjVWfycTKaUUb7CHAU6JH8zQ1DPsTQ+F+W+q1RZZCj1qUBO9cHe9xIPWoK6PN829/UmZAzJeyg==
|
||||
-----END PRIVATE KEY-----
|
||||
3
extend/encryption/cert/rsa_public_key.pem
Normal file
3
extend/encryption/cert/rsa_public_key.pem
Normal file
@@ -0,0 +1,3 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm+F9cDfa3rdu9YFq7F5UsphYp5YXjFM9pCLMikRLZXxO2ox+gZuWxBcXvx5wg8Yd+3pFCauCTHlNWsCYGAOJpb2kOuw0n+PwGVpNg4PEy0GhO1XgSaD2nQ8nIiMLhYXFgdpXw+tikZW16oI344uyI2ROMrFQffQ6H6SfXPcXdDbc87gTY4MYfn+gbHoLCJKiyKShiDjXj62PXAo/rzjGkXVIFnM0Dn7Vl7SV4kc+ZFMcFegkkEG2zxRMkkrZVtljARdeRcnjk1xEb6YDqD+Dvo/9BjFt0fuHSlMRWPkj65jDAeh5iYMkoAiFbsJVCci5ZoWbmiLpq8sidfWHPowdGQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
89
extend/sitemap/sitemap.config.php
Normal file
89
extend/sitemap/sitemap.config.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/*
|
||||
Sitemap Generator by Slava Knyazev. Further acknowledgements in the README.md file.
|
||||
|
||||
Website: https://www.knyz.org/
|
||||
I also live on GitHub: https://github.com/knyzorg
|
||||
Contact me: Slava@KNYZ.org
|
||||
*/
|
||||
|
||||
//Make sure to use the latest revision by downloading from github: https://github.com/knyzorg/Sitemap-Generator-Crawler
|
||||
|
||||
/* Usage
|
||||
Usage is pretty strait forward:
|
||||
- Configure the crawler by editing this file.
|
||||
- Select the file to which the sitemap will be saved
|
||||
- Select URL to crawl
|
||||
- Configure blacklists, accepts the use of wildcards (example: http://example.com/private/* and *.jpg)
|
||||
- Generate sitemap
|
||||
- Either send a GET request to this script or run it from the command line (refer to README file)
|
||||
- Submit to Google
|
||||
- Setup a CRON Job execute this script every so often
|
||||
|
||||
It is recommended you don't remove the above for future reference.
|
||||
*/
|
||||
|
||||
// Default site to crawl
|
||||
$site = "https://www.knyz.org/";
|
||||
|
||||
// Default sitemap filename
|
||||
$file = "sitemap.xml";
|
||||
$permissions = 0644;
|
||||
|
||||
// Depth of the crawl, 0 is unlimited
|
||||
$max_depth = 0;
|
||||
|
||||
// Show changefreq
|
||||
$enable_frequency = false;
|
||||
|
||||
// Show priority
|
||||
$enable_priority = false;
|
||||
|
||||
// Default values for changefreq and priority
|
||||
$freq = "daily";
|
||||
$priority = "1";
|
||||
|
||||
// Add lastmod based on server response. Unreliable and disabled by default.
|
||||
$enable_modified = false;
|
||||
|
||||
// Disable this for misconfigured, but tolerable SSL server.
|
||||
$curl_validate_certificate = true;
|
||||
|
||||
// The pages will be excluded from crawl and sitemap.
|
||||
// Use for exluding non-html files to increase performance and save bandwidth.
|
||||
$blacklist = array(
|
||||
"*.jpg",
|
||||
"*/secrets/*",
|
||||
"https://www.knyz.org/supersecret"
|
||||
);
|
||||
|
||||
// Enable this if your site do requires GET arguments to function
|
||||
$ignore_arguments = false;
|
||||
|
||||
// Not yet implemented. See issue #19 for more information.
|
||||
$index_img = false;
|
||||
|
||||
//Index PDFs
|
||||
$index_pdf = true;
|
||||
|
||||
// Set the user agent for crawler
|
||||
$crawler_user_agent = "Mozilla/5.0 (compatible; Sitemap Generator Crawler; +https://github.com/knyzorg/Sitemap-Generator-Crawler)";
|
||||
|
||||
// Header of the sitemap.xml
|
||||
$xmlheader ='<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset
|
||||
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
|
||||
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';
|
||||
|
||||
// Optionally configure debug options
|
||||
$debug = array(
|
||||
"add" => true,
|
||||
"reject" => false,
|
||||
"warn" => false
|
||||
);
|
||||
|
||||
|
||||
//Modify only if configuration version is broken
|
||||
$version_config = 2;
|
||||
426
extend/sitemap/sitemap.functions.php
Normal file
426
extend/sitemap/sitemap.functions.php
Normal file
@@ -0,0 +1,426 @@
|
||||
<?php
|
||||
|
||||
// Abstracted function to output formatted logging
|
||||
function logger($message, $type)
|
||||
{
|
||||
global $debug, $color;
|
||||
if ($color) {
|
||||
switch ($type) {
|
||||
case 0:
|
||||
//add
|
||||
echo $debug["add"] ? "\033[0;32m [+] $message \033[0m\n" : "";
|
||||
break;
|
||||
case 1:
|
||||
//reject
|
||||
echo $debug["reject"] ? "\033[0;31m [-] $message \033[0m\n" : "";
|
||||
break;
|
||||
case 2:
|
||||
//manipulate
|
||||
echo $debug["warn"] ? "\033[1;33m [!] $message \033[0m\n" : "";
|
||||
break;
|
||||
case 3:
|
||||
//critical
|
||||
echo "\033[1;33m [!] $message \033[0m\n";
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch ($type) {
|
||||
case 0:
|
||||
//add
|
||||
echo $debug["add"] ? "[+] $message\n" : "";
|
||||
break;
|
||||
case 1:
|
||||
//reject
|
||||
echo $debug["reject"] ? "31m [-] $message\n" : "";
|
||||
break;
|
||||
case 2:
|
||||
//manipulate
|
||||
echo $debug["warn"] ? "[!] $message\n" : "";
|
||||
break;
|
||||
case 3:
|
||||
//critical
|
||||
echo "[!] $message\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function flatten_url($url)
|
||||
{
|
||||
global $real_site;
|
||||
$path = explode($real_site, $url)[1];
|
||||
return $real_site . remove_dot_seg($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dot segments from a URI path according to RFC3986 Section 5.2.4
|
||||
*
|
||||
* @param $path
|
||||
* @return string
|
||||
* @link http://www.ietf.org/rfc/rfc3986.txt
|
||||
*/
|
||||
function remove_dot_seg($path)
|
||||
{
|
||||
if (strpos($path, '.') === false) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
$inputBuffer = $path;
|
||||
$outputStack = [];
|
||||
|
||||
/**
|
||||
* 2. While the input buffer is not empty, loop as follows:
|
||||
*/
|
||||
while ($inputBuffer != '') {
|
||||
/**
|
||||
* A. If the input buffer begins with a prefix of "../" or "./",
|
||||
* then remove that prefix from the input buffer; otherwise,
|
||||
*/
|
||||
if (strpos($inputBuffer, "./") === 0) {
|
||||
$inputBuffer = substr($inputBuffer, 2);
|
||||
continue;
|
||||
}
|
||||
if (strpos($inputBuffer, "../") === 0) {
|
||||
$inputBuffer = substr($inputBuffer, 3);
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* B. if the input buffer begins with a prefix of "/./" or "/.",
|
||||
* where "." is a complete path segment, then replace that
|
||||
* prefix with "/" in the input buffer; otherwise,
|
||||
*/
|
||||
if ($inputBuffer === "/.") {
|
||||
$outputStack[] = '/';
|
||||
break;
|
||||
}
|
||||
if (substr($inputBuffer, 0, 3) === "/./") {
|
||||
$inputBuffer = substr($inputBuffer, 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* C. if the input buffer begins with a prefix of "/../" or "/..",
|
||||
* where ".." is a complete path segment, then replace that
|
||||
* prefix with "/" in the input buffer and remove the last
|
||||
* segment and its preceding "/" (if any) from the output
|
||||
* buffer; otherwise,
|
||||
*/
|
||||
if ($inputBuffer === "/..") {
|
||||
array_pop($outputStack);
|
||||
$outputStack[] = '/';
|
||||
break;
|
||||
}
|
||||
if (substr($inputBuffer, 0, 4) === "/../") {
|
||||
array_pop($outputStack);
|
||||
$inputBuffer = substr($inputBuffer, 3);
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* D. if the input buffer consists only of "." or "..", then remove
|
||||
* that from the input buffer; otherwise,
|
||||
*/
|
||||
if ($inputBuffer === '.' || $inputBuffer === '..') {
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* E. move the first path segment in the input buffer to the end of
|
||||
* the output buffer, including the initial "/" character (if
|
||||
* any) and any subsequent characters up to, but not including,
|
||||
* the next "/" character or the end of the input buffer.
|
||||
*/
|
||||
if (($slashPos = stripos($inputBuffer, '/', 1)) === false) {
|
||||
$outputStack[] = $inputBuffer;
|
||||
break;
|
||||
} else {
|
||||
$outputStack[] = substr($inputBuffer, 0, $slashPos);
|
||||
$inputBuffer = substr($inputBuffer, $slashPos);
|
||||
}
|
||||
}
|
||||
|
||||
return ltrim(implode($outputStack), "/");
|
||||
}
|
||||
|
||||
// Check if a URL has already been scanned
|
||||
function is_scanned($url)
|
||||
{
|
||||
global $scanned;
|
||||
|
||||
if (isset($scanned[$url])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check if in array as dir and non-dir
|
||||
$url = ends_with($url, "/") ? substr($url, 0, -1) : $url . "/";
|
||||
if (isset($scanned[$url])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function ends_with($haystack, $needle)
|
||||
{
|
||||
$length = strlen($needle);
|
||||
if ($length == 0) {
|
||||
return true;
|
||||
}
|
||||
return (substr($haystack, -$length) === $needle);
|
||||
}
|
||||
|
||||
// Gets path for a relative linl
|
||||
// https://somewebsite.com/directory/file => https://somewebsite.com/directory/
|
||||
// https://somewebsite.com/directory/subdir/ => https://somewebsite.com/directory/subdir/
|
||||
function get_path($path)
|
||||
{
|
||||
$path_depth = explode("/", $path);
|
||||
$len = strlen($path_depth[count($path_depth) - 1]);
|
||||
return (substr($path, 0, strlen($path) - $len));
|
||||
}
|
||||
|
||||
//Get the root of the domain
|
||||
function domain_root($href)
|
||||
{
|
||||
$url_parts = explode('/', $href);
|
||||
return $url_parts[0] . '//' . $url_parts[2] . '/';
|
||||
}
|
||||
|
||||
//The curl client is create outside of the function to avoid re-creating it for performance reasons
|
||||
$curl_client = curl_init();
|
||||
function get_data($url)
|
||||
{
|
||||
global $curl_validate_certificate, $curl_client, $index_pdf, $crawler_user_agent, $enable_modified;
|
||||
|
||||
//Set URL
|
||||
curl_setopt($curl_client, CURLOPT_URL, $url);
|
||||
//Follow redirects and get new url
|
||||
curl_setopt($curl_client, CURLOPT_RETURNTRANSFER, 1);
|
||||
//Get headers
|
||||
curl_setopt($curl_client, CURLOPT_HEADER, 1);
|
||||
//Optionally avoid validating SSL
|
||||
curl_setopt($curl_client, CURLOPT_SSL_VERIFYPEER, $curl_validate_certificate);
|
||||
//Set user agent
|
||||
curl_setopt($curl_client, CURLOPT_USERAGENT, $crawler_user_agent);
|
||||
|
||||
//Get data
|
||||
$data = curl_exec($curl_client);
|
||||
$content_type = curl_getinfo($curl_client, CURLINFO_CONTENT_TYPE);
|
||||
$http_code = curl_getinfo($curl_client, CURLINFO_HTTP_CODE);
|
||||
$redirect_url = curl_getinfo($curl_client, CURLINFO_REDIRECT_URL);
|
||||
|
||||
//Scan new url, if redirect
|
||||
if ($redirect_url) {
|
||||
logger("URL is a redirect.", 1);
|
||||
if (strpos($redirect_url, '?') !== false) {
|
||||
$redirect_url = explode($redirect_url, "?")[0];
|
||||
}
|
||||
unset($url, $data);
|
||||
|
||||
if (!check_blacklist($redirect_url)) {
|
||||
echo logger("Redirected URL is in blacklist", 1);
|
||||
|
||||
} else {
|
||||
scan_url($redirect_url);
|
||||
}
|
||||
}
|
||||
|
||||
//If content acceptable, return it. If not, `false`
|
||||
$html = ($http_code != 200 || (!stripos($content_type, "html"))) ? false : $data;
|
||||
|
||||
//Additional data
|
||||
if ($enable_modified){
|
||||
curl_setopt($curl_client, CURLOPT_FILETIME, true);
|
||||
$timestamp = curl_getinfo($curl_client, CURLINFO_FILETIME);
|
||||
$modified = ($timestamp != -1) ? date('c', $timestamp) : null;
|
||||
}
|
||||
else $modified = null;
|
||||
|
||||
if (stripos($content_type, "application/pdf") !== false && $index_pdf) {
|
||||
$html = "This is a PDF";
|
||||
}
|
||||
//Return it as an array
|
||||
return array($html, $modified, (stripos($content_type, "image/") && $index_img));
|
||||
}
|
||||
|
||||
//Try to match string against blacklist
|
||||
function check_blacklist($string)
|
||||
{
|
||||
global $blacklist;
|
||||
if (is_array($blacklist)) {
|
||||
foreach ($blacklist as $illegal) {
|
||||
if (fnmatch($illegal, $string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Extract array of URLs from html document inside of `href`s
|
||||
function get_links($html, $parent_url, $regexp)
|
||||
{
|
||||
if (preg_match_all("/$regexp/siU", $html, $matches)) {
|
||||
if ($matches[2]) {
|
||||
$found = array_map(function ($href) use (&$parent_url) {
|
||||
global $real_site, $ignore_arguments;
|
||||
|
||||
logger("Checking $href", 2);
|
||||
|
||||
if (strpos($href, "#") !== false) {
|
||||
logger("Dropping pound.", 2);
|
||||
$href = preg_replace('/\#.*/', '', $href);
|
||||
}
|
||||
|
||||
//Seperate $href from $query_string
|
||||
$query_string = '';
|
||||
if (strpos($href, '?') !== false) {
|
||||
list($href, $query_string) = explode('?', $href);
|
||||
|
||||
//Parse & to not break curl client. See issue #23
|
||||
$query_string = str_replace('&', '&', $query_string);
|
||||
}
|
||||
if ($ignore_arguments) {
|
||||
$query_string = '';
|
||||
}
|
||||
if (strpos($href, '?') !== false) {
|
||||
echo "EFEASDEFSED";
|
||||
}
|
||||
|
||||
if ((substr($href, 0, 7) != "http://") && (substr($href, 0, 8) != "https://")) {
|
||||
// Link does not call (potentially) external page
|
||||
if (strpos($href, ":")) {
|
||||
logger("URL is an invalid protocol", 1);
|
||||
return false;
|
||||
}
|
||||
if ($href == '/') {
|
||||
logger("$href is domain root", 2);
|
||||
$href = $real_site;
|
||||
} elseif (substr($href, 0, 1) == '/') {
|
||||
logger("$href is relative to root, convert to absolute", 2);
|
||||
$href = domain_root($real_site) . substr($href, 1);
|
||||
} else {
|
||||
logger("$href is relative, convert to absolute", 2);
|
||||
$href = get_path($parent_url) . $href;
|
||||
}
|
||||
}
|
||||
logger("Result: $href", 2);
|
||||
if (!filter_var($href, FILTER_VALIDATE_URL)) {
|
||||
logger("URL is not valid. Rejecting.", 1);
|
||||
return false;
|
||||
}
|
||||
if (substr($href, 0, strlen($real_site)) != $real_site) {
|
||||
logger("URL is not part of the target domain. Rejecting.", 1);
|
||||
return false;
|
||||
}
|
||||
if (is_scanned($href . ($query_string ? '?' . $query_string : ''))) {
|
||||
//logger("URL has already been scanned. Rejecting.", 1);
|
||||
return false;
|
||||
}
|
||||
if (!check_blacklist($href)) {
|
||||
logger("URL is blacklisted. Rejecting.", 1);
|
||||
return false;
|
||||
}
|
||||
return flatten_url($href . ($query_string ? '?' . $query_string : ''));
|
||||
}, $matches[2]);
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
logger("Found nothing", 2);
|
||||
return array();
|
||||
}
|
||||
|
||||
function scan_url($url)
|
||||
{
|
||||
global $scanned, $deferredLinks, $file_stream, $freq, $priority, $enable_priority, $enable_frequency, $max_depth, $depth, $real_site, $indexed;
|
||||
$depth++;
|
||||
|
||||
logger("Scanning $url", 2);
|
||||
if (is_scanned($url)) {
|
||||
logger("URL has already been scanned. Rejecting.", 1);
|
||||
return $depth--;
|
||||
}
|
||||
if (substr($url, 0, strlen($real_site)) != $real_site) {
|
||||
logger("URL is not part of the target domain. Rejecting.", 1);
|
||||
return $depth--;
|
||||
}
|
||||
if (!($depth <= $max_depth || $max_depth == 0)) {
|
||||
logger("Maximum depth exceeded. Rejecting.", 1);
|
||||
return $depth--;
|
||||
}
|
||||
|
||||
//Note that URL has been scanned
|
||||
$scanned[$url] = 1;
|
||||
|
||||
//Send cURL request
|
||||
list($html, $modified, $is_image) = get_data($url);
|
||||
|
||||
if ($is_image) {
|
||||
//Url is an image
|
||||
}
|
||||
|
||||
if (!$html) {
|
||||
logger("Invalid Document. Rejecting.", 1);
|
||||
return $depth--;
|
||||
}
|
||||
|
||||
if (strpos($url, "&") && strpos($url, ";") === false) {
|
||||
$url = str_replace("&", "&", $url);
|
||||
}
|
||||
|
||||
$map_row = "<url>\n";
|
||||
$map_row .= "<loc>$url</loc>\n";
|
||||
if ($enable_frequency) {
|
||||
$map_row .= "<changefreq>$freq</changefreq>\n";
|
||||
}
|
||||
if ($enable_priority) {
|
||||
$map_row .= "<priority>$priority</priority>\n";
|
||||
}
|
||||
if ($modified) {
|
||||
$map_row .= " <lastmod>$modified</lastmod>\n";
|
||||
}
|
||||
$map_row .= "</url>\n";
|
||||
fwrite($file_stream, $map_row);
|
||||
$indexed++;
|
||||
logger("Added: " . $url . (($modified) ? " [Modified: " . $modified . "]" : ''), 0);
|
||||
unset($is_image, $map_row);
|
||||
|
||||
// Extract urls from <a href="??"></a>
|
||||
$ahrefs = get_links($html, $url, "<a\s[^>]*href=(\"|'??)([^\" >]*?)\\1[^>]*>(.*)<\/a>");
|
||||
|
||||
// Extract urls from <frame src="??">
|
||||
$framesrc = get_links($html, $url, "<frame\s[^>]*src=(\"|'??)([^\" >]*?)\\1[^>]*>");
|
||||
|
||||
$links = array_filter(array_merge($ahrefs, $framesrc), function ($item) use (&$deferredLinks) {
|
||||
return $item && !isset($deferredLinks[$item]);
|
||||
});
|
||||
unset($html, $url, $ahrefs, $framesrc);
|
||||
|
||||
logger("Found urls: " . join(", ", $links), 2);
|
||||
|
||||
//Note that URL has been deferred
|
||||
foreach ($links as $href) {
|
||||
if ($href) {
|
||||
$deferredLinks[$href] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($links as $href) {
|
||||
if ($href) {
|
||||
scan_url($href);
|
||||
}
|
||||
}
|
||||
$depth--;
|
||||
}
|
||||
|
||||
// fnmatch() filler for non-POSIX systems
|
||||
|
||||
if (!function_exists('fnmatch')) {
|
||||
function fnmatch($pattern, $string)
|
||||
{
|
||||
return preg_match("#^" . strtr(preg_quote($pattern, '#'), array('\*' => '.*', '\?' => '.')) . "$#i", $string);
|
||||
} // end
|
||||
} // end if
|
||||
|
||||
$version_functions = 2;
|
||||
128
extend/sitemap/sitemap.php
Normal file
128
extend/sitemap/sitemap.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/***************************\
|
||||
|***DO NOT EDIT THIS FILE***|
|
||||
|**EDIT sitemap.config.php**|
|
||||
\***************************/
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
//Read global variables from config file
|
||||
require_once( 'sitemap.config.php' );
|
||||
|
||||
// Include all functions
|
||||
require_once('sitemap.functions.php');
|
||||
|
||||
//Default html header makes browsers ignore \n
|
||||
header("Content-Type: text/plain");
|
||||
|
||||
$color = false;
|
||||
|
||||
$version_script = 2;
|
||||
|
||||
if ($version_script != $version_functions || $version_functions != $version_config){
|
||||
logger("Script versions mismatch!",3);
|
||||
logger("Update necessary",3);
|
||||
logger("Version of sitemap.functions.php " .$version_functions ,3);
|
||||
logger("Version of sitemap.config.php " .$version_config ,3);
|
||||
logger("Version of sitemap.php " .$version_script ,3);
|
||||
logger("Download new files here: https://www.github.com/knyzorg/sitemap-generator-crawler" ,3);
|
||||
die("Stopped.");
|
||||
}
|
||||
|
||||
// Add PHP CLI support
|
||||
if (php_sapi_name() === 'cli' && PHP_OS != 'WINNT') {
|
||||
parse_str(implode('&', array_slice($argv, 1)), $args);
|
||||
$color = true;
|
||||
}
|
||||
|
||||
//Allow variable overloading with CLI
|
||||
if (isset($args['file'])) {
|
||||
$file = $args['file'];
|
||||
}
|
||||
if (isset($args['site'])) {
|
||||
$site = $args['site'];
|
||||
}
|
||||
if (isset($args['max_depth'])) {
|
||||
$max_depth = $args['max_depth'];
|
||||
}
|
||||
if (isset($args['enable_frequency'])) {
|
||||
$enable_frequency = $args['enable_frequency'];
|
||||
}
|
||||
if (isset($args['enable_priority'])) {
|
||||
$enable_priority = $args['enable_priority'];
|
||||
}
|
||||
if (isset($args['enable_modified'])) {
|
||||
$enable_modified = $args['enable_modified'];
|
||||
}
|
||||
if (isset($args['freq'])) {
|
||||
$freq = $args['freq'];
|
||||
}
|
||||
if (isset($args['priority'])) {
|
||||
$priority = $args['priority'];
|
||||
}
|
||||
if (isset($args['blacklist'])) {
|
||||
$blacklist = $args['blacklist'];
|
||||
}
|
||||
if (isset($args['debug'])) {
|
||||
$debug = $args['debug'];
|
||||
}
|
||||
if (isset($args['ignore_arguments'])) {
|
||||
$ignore_arguments = !!$args['ignore_arguments'];
|
||||
}
|
||||
if (isset($args['pdf_index'])) {
|
||||
$pdf_index = $args['pdf_index'];
|
||||
}
|
||||
|
||||
//Begin stopwatch for statistics
|
||||
$start = microtime(true);
|
||||
|
||||
//Setup file stream
|
||||
$tempfile = tempnam(sys_get_temp_dir(), 'sitemap.xml.');
|
||||
$file_stream = fopen($tempfile, "w") or die("Error: Could not create temporary file $tempfile" . "\n");
|
||||
|
||||
fwrite($file_stream, $xmlheader);
|
||||
|
||||
// Global variable, non-user defined
|
||||
$depth = 0;
|
||||
$indexed = 0;
|
||||
$scanned = array();
|
||||
$deferredLinks = array();
|
||||
|
||||
// Reduce domain to root in case of monkey
|
||||
$real_site = domain_root($site);
|
||||
|
||||
if ($real_site != $site){
|
||||
logger("Reformatted site from $site to $real_site", 2);
|
||||
}
|
||||
|
||||
// Begin by crawling the original url
|
||||
scan_url($real_site);
|
||||
|
||||
// Finalize sitemap
|
||||
fwrite($file_stream, "</urlset>\n");
|
||||
fclose($file_stream);
|
||||
|
||||
// Pretty-print sitemap
|
||||
if ((PHP_OS == 'WINNT') ? `where xmllint` : `which xmllint`) {
|
||||
logger("Found xmllint, pretty-printing sitemap", 0);
|
||||
$responsevalue = exec('xmllint --format ' . $tempfile . ' -o ' . $tempfile . ' 2>&1', $discardedoutputvalue, $returnvalue);
|
||||
if ($returnvalue) {
|
||||
die("Error: " . $responsevalue . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Generate and print out statistics
|
||||
$time_elapsed_secs = round(microtime(true) - $start, 2);
|
||||
logger("Sitemap has been generated in " . $time_elapsed_secs . " second" . (($time_elapsed_secs >= 1 ? 's' : '') . "and saved to $file"), 0);
|
||||
$size = sizeof($scanned);
|
||||
logger("Scanned a total of $size pages and indexed $indexed pages.", 0);
|
||||
|
||||
// Rename partial file to the real file name. `rename()` overwrites any existing files
|
||||
rename($tempfile, $file);
|
||||
|
||||
// Apply permissions
|
||||
chmod($file, $permissions);
|
||||
|
||||
// Declare that the script has finished executing and exit
|
||||
logger("Operation Completed", 0);
|
||||
115
extend/sso/SSOClient.php
Normal file
115
extend/sso/SSOClient.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
namespace sso;
|
||||
|
||||
use apiRes\Api;
|
||||
use think\facade\Session;
|
||||
|
||||
class SSOClient
|
||||
{
|
||||
private $sso_url = '';
|
||||
private $app_id = '';
|
||||
private $app_secret = '';
|
||||
private $public_ssl_key = '';
|
||||
private $private_ssl_key = '';
|
||||
|
||||
public function __construct($data)
|
||||
{
|
||||
// $this->sso_url = config('sso.sso_url');
|
||||
// if (config('sso.app_id')) $this->app_id = config('sso.app_id');
|
||||
// if (config('sso.app_secret')) $this->app_secret = config('sso.app_secret');
|
||||
// if (config('sso.public_key')) $this->public_ssl_key = config('sso.public_key');
|
||||
// if (config('sso.private_key')) $this->private_ssl_key = config('sso.private_key');
|
||||
|
||||
$this->app_id = $data['app_id'];
|
||||
$this->sso_url = $data['sso_url'];
|
||||
$this->app_secret = $data['app_secret'];
|
||||
$this->public_ssl_key = $data['public_key'];
|
||||
$this->private_ssl_key = $data['private_key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验code,返回access_token
|
||||
*/
|
||||
public function getAccessToken($code)
|
||||
{
|
||||
if (empty($code)) {
|
||||
return Api::error('参数code不能为空', [], true);
|
||||
}
|
||||
$data = [
|
||||
'app_id' => $this->app_id,
|
||||
'app_secret' => $this->app_secret,
|
||||
'code' => $code
|
||||
];
|
||||
return $this->http('authorize/access_token', $data, true, ['cookie'=>'PHPSESSID=' . Session::getId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新access_token
|
||||
*/
|
||||
public function refreshToken($refresh_token, $sessid='')
|
||||
{
|
||||
if (empty($refresh_token)) {
|
||||
return Api::error('参数refresh_token不能为空', [], true);
|
||||
}
|
||||
$data = [
|
||||
'app_id' => $this->app_id,
|
||||
'app_secret' => $this->app_secret,
|
||||
'refresh_token' => $refresh_token
|
||||
];
|
||||
return $this->http('authorize/refresh_token', $data, true, ['cookie'=>'PHPSESSID=' . $sessid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知sso退出登录
|
||||
*/
|
||||
public function notifySSOServerSigninOut($access_token, $sessid='')
|
||||
{
|
||||
if (empty($access_token)) {
|
||||
return Api::error('参数access_token不能为空', [], true);
|
||||
}
|
||||
$data = [
|
||||
'app_id' => $this->app_id,
|
||||
'app_secret' => $this->app_secret,
|
||||
'access_token' => $access_token,
|
||||
];
|
||||
if (empty($sessid)) {
|
||||
$sessid = Session::getId();
|
||||
}
|
||||
return $this->http('authorize/signin_out', $data, true, ['cookie'=>'PHPSESSID=' . $sessid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求数据
|
||||
*/
|
||||
private function http($url, $data, $is_post=false, $options=[])
|
||||
{
|
||||
$data = json_encode($data);
|
||||
$headerArray = [
|
||||
'Content-type: application/json;charset=utf-8',
|
||||
'Accept: application/json'
|
||||
];
|
||||
$url = $this->sso_url . $url;
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
|
||||
if ($is_post) {
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
if (!empty($options['cookie'])) {
|
||||
curl_setopt($curl, CURLOPT_COOKIE, $options['cookie']);
|
||||
}
|
||||
$output = curl_exec($curl);
|
||||
$http_status = curl_errno($curl);
|
||||
$http_msg = curl_error($curl);
|
||||
curl_close($curl);
|
||||
if ($http_status == 0) {
|
||||
return json_decode($output, true);
|
||||
} else {
|
||||
return ['errno' => $http_status, 'errmsg' => $http_msg, 'data' => []];
|
||||
}
|
||||
}
|
||||
}
|
||||
204
extend/storage/LocalUploader.php
Normal file
204
extend/storage/LocalUploader.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
namespace storage;
|
||||
|
||||
use FceskyUpload\contract\FileInfo;
|
||||
use FceskyUpload\UploadManager;
|
||||
use FceskyUpload\drivers\LocalDriver;
|
||||
|
||||
class LocalUploader
|
||||
{
|
||||
private $config = [];
|
||||
private $domain = "";
|
||||
private $_error = "";
|
||||
|
||||
public function __construct($conf = [])
|
||||
{
|
||||
$this->config = [
|
||||
'disks' => [
|
||||
'local' => [
|
||||
'driver' => LocalDriver::class, //上传类
|
||||
'save_dir' => app()->getRootPath() . 'public/attachment', //上传保存路径
|
||||
'file_path' => '/attachment', //上传保存路径
|
||||
'tmp_dir' => root_path('runtime' . DIRECTORY_SEPARATOR . 'uploadtmp'),//临时目录
|
||||
'slice_first' => 0, //从第几片开始
|
||||
],
|
||||
//继续添加其它仓库
|
||||
],
|
||||
'default' => [
|
||||
'disk' => 'local', //默认磁盘
|
||||
'extensions' => 'jpg,png,mp4', //后缀
|
||||
'mimeTypes' => 'image/*,video/*', //类型
|
||||
'middlewares' => [], //中间件数组
|
||||
'maxSize' => 1 * 1024 * 1024, //单包最大上传大小 2M
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**文件上传
|
||||
* @param $data
|
||||
* @param $file
|
||||
* @return array
|
||||
*/
|
||||
public function uploadFile($data, $file)
|
||||
{
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
|
||||
exit; // finish preflight CORS requests here
|
||||
}
|
||||
|
||||
try {
|
||||
//处理部分数据
|
||||
$data['size'] = $file->getSize();
|
||||
$data['name'] = $file->getOriginalName();
|
||||
$data['ext'] = $file->extension();
|
||||
//检测文件大小
|
||||
if (!$this->checkSize($data['size'])) {
|
||||
$this->_error = "超出文件上传大小限制";
|
||||
return ['code' => -1, 'data' => []];
|
||||
}
|
||||
$config = $this->config;
|
||||
$uploadManager = new UploadManager($config);
|
||||
$fileInfo = new FileInfo();
|
||||
$fileInfo->identifier = $data['hash'];
|
||||
$fileInfo->filename = $data['name'];
|
||||
|
||||
$fileInfo->chunkNumber = $data['chunk'] ?? 0;;
|
||||
$fileInfo->chunkNumber = intval($fileInfo->chunkNumber ?? 0);
|
||||
|
||||
//未设置分片数量 则默认总数为1 当前为0
|
||||
$fileInfo->totalChunks = $data['chunks'] ?? 1;
|
||||
$fileInfo->totalChunks = intval($fileInfo->totalChunks ?? 1);
|
||||
$fileInfo->totalChunks = ($fileInfo->totalChunks > 0) ? $fileInfo->totalChunks : 1;
|
||||
$fileInfo->totalSize = $data['size'];
|
||||
//获取后缀
|
||||
|
||||
$fileInfo->ext = $data['ext'];
|
||||
if (!$this->checkFileType($fileInfo->ext)) {
|
||||
$this->_error = "禁止上传的文件类型";
|
||||
return ['code' => -1, 'data' => []];
|
||||
}
|
||||
|
||||
$upload = $uploadManager->uploadFile($fileInfo);
|
||||
//如果文件较小 直接上传完成
|
||||
if (isset($upload['savepath']) && $upload['code'] == 0) {
|
||||
$upload = $this->buildFileUrl($upload);
|
||||
return ['code' => 1, 'data' => $upload, 'msg' => '成功'];
|
||||
}
|
||||
$check = $uploadManager->checkFile($fileInfo);
|
||||
//如果上传完成
|
||||
if (isset($check['savepath']) && $check['code'] == 0) {
|
||||
$check = $this->buildFileUrl($check);
|
||||
return ['code' => 1, 'data' => $check];
|
||||
} else {
|
||||
$this->_error = "文件包不完整";
|
||||
return ['code' => 0, 'data' => $check];
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->_error = $e->getMessage();
|
||||
return ['code' => -1, 'data' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理文件
|
||||
* 扩展包存在问题 ,考虑后续更新 尽量不更改扩展包,在这里做文件的处理
|
||||
*/
|
||||
public function buildFileUrl($data)
|
||||
{
|
||||
|
||||
if (isset($data['savepath']) && $data['savepath'] != '') {
|
||||
|
||||
$conf = $this->config;
|
||||
//获取除域名外的文件路径
|
||||
$save_dir = $conf['disks'][$conf['default']['disk']]['save_dir'];
|
||||
$file_path = str_replace($save_dir, '', $data['savepath']);
|
||||
//拼接域名
|
||||
$data['save_path'] = $conf['disks'][$conf['default']['disk']]['file_path'] . $file_path;
|
||||
$data['file_path'] = $this->domain . $data['save_path'];
|
||||
//删除多余的信息
|
||||
unset($data['savepath']);
|
||||
unset($data['code']);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
//检测文件上传大小
|
||||
public function checkSize($file_size)
|
||||
{
|
||||
|
||||
if ($file_size > $this->config['default']['maxSize']) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**检测文件类型
|
||||
* @param $file_ext
|
||||
* @return array|bool
|
||||
*/
|
||||
public function checkFileType($file_ext)
|
||||
{ //获取配置信息
|
||||
$extensions = $this->config['default']['extensions'];
|
||||
|
||||
//为空或者为 * 表示不过滤
|
||||
if ($extensions == "" || $extensions == '*') {
|
||||
return true;
|
||||
}
|
||||
//字符转换成数组
|
||||
$exts = explode(',', $extensions);
|
||||
if (in_array($file_ext, $exts)) {
|
||||
$this->_error = "禁止上传该类型文件";
|
||||
return ['code' => 0, 'data' => ''];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测文件分片情况
|
||||
*/
|
||||
public function checkFile($hash,$count){
|
||||
|
||||
$filePath = $this->config['disks'][$this->config['default']['disk']]['tmp_dir'] . $hash; //临时分片文件路径
|
||||
|
||||
// dump($filePath);
|
||||
//检查分片是否存在
|
||||
$chunkExists = [];
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
if (file_exists("{$filePath}_{$index}")) {
|
||||
array_push($chunkExists, $index);
|
||||
}
|
||||
}
|
||||
//分片有缺失,返回已存在的分片
|
||||
$res['uploaded'] = $chunkExists;
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param $path
|
||||
*/
|
||||
public function deleteFile($path){
|
||||
$path = app()->getRootPath() . 'public'.$path;
|
||||
if (file_exists($path)){
|
||||
@unlink($path);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回报错
|
||||
* @return string
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->_error;
|
||||
}
|
||||
|
||||
}
|
||||
160
extend/storage/QiniuUploader.php
Normal file
160
extend/storage/QiniuUploader.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace storage;
|
||||
|
||||
use Qiniu\Auth;
|
||||
use Qiniu\Storage\UploadManager;
|
||||
use Qiniu\Storage\BucketManager;
|
||||
|
||||
class QiniuUploader
|
||||
{
|
||||
private $bucket = 'orico-opd';
|
||||
private $accessKey = 'dOsTum4a5qvhPTBbZRPX0pIOU7PZWRX7htKjztms';
|
||||
private $secretKey = 'KFxsGbnErkALFfeGdMa8QWTdodJbamMX0iznLe-q';
|
||||
|
||||
private $rule = [
|
||||
'fileSize' => 1024 * 1024 * 5, // 默认最大上传5M
|
||||
'fileExt' => 'jpeg,jpg,png', // 默认上传文件后缀
|
||||
'fileMime' => 'image/jpeg,image/png,image/gif' // 默认上传文件mime
|
||||
];
|
||||
|
||||
private $dir = true;
|
||||
private $originalName = false;
|
||||
private $pathPrefix = '';
|
||||
private $fileNamePrefix = 'orico';
|
||||
|
||||
static public $domain = 'http://opdfile.f2b211.com/';
|
||||
|
||||
public function __construct($conf = [])
|
||||
{
|
||||
if (!empty($conf['bucket'])) {
|
||||
$this->bucket = $conf['bucket'];
|
||||
}
|
||||
if (!empty($conf['accessKey'])) {
|
||||
$this->accessKey = $conf['accessKey'];
|
||||
}
|
||||
if (!empty($conf['secretKey'])) {
|
||||
$this->secretKey = $conf['secretKey'];
|
||||
}
|
||||
if (!empty($conf['pathPrefix'])) {
|
||||
$this->pathPrefix = trim($conf['pathPrefix'], '/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机字符串
|
||||
*/
|
||||
private function random($length, $type = "string", $convert = "0")
|
||||
{
|
||||
$conf = [
|
||||
'number' => '0123456789',
|
||||
'string' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789='
|
||||
];
|
||||
$string = $conf[$type];
|
||||
if (!$string) {
|
||||
$string = $conf['string'];
|
||||
}
|
||||
$strlen = strlen($string) - 1;
|
||||
$char = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$char .= $string[mt_rand(0, $strlen)];
|
||||
}
|
||||
if ($convert > 0) {
|
||||
$res = strtoupper($char);
|
||||
} elseif ($convert == 0) {
|
||||
$res = $char;
|
||||
} elseif ($convert < 0) {
|
||||
$res = strtolower($char);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装文件名
|
||||
*/
|
||||
private function buildFileName()
|
||||
{
|
||||
return $this->fileNamePrefix . time() . substr(time(), -5) . substr(microtime(), 2, 3) . $this->random(8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传验证规则
|
||||
*/
|
||||
public function validate($rule)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到七牛云
|
||||
*/
|
||||
public function uploadFile($name)
|
||||
{
|
||||
// 构建鉴权对象
|
||||
$auth = new Auth($this->accessKey, $this->secretKey);
|
||||
|
||||
// 生成上传 Token
|
||||
$token = $auth->uploadToken($this->bucket);
|
||||
|
||||
// 初始化 UploadManager 对象并进行文件的上传。
|
||||
$uploadMgr = new UploadManager();
|
||||
|
||||
$file = request()->file($name);
|
||||
|
||||
$aspectRatio = [];
|
||||
if (!empty($this->rule['aspectRatio'])) {
|
||||
$aspectRatio = $this->rule['aspectRatio'];
|
||||
unset($this->rule['aspectRatio']);
|
||||
}
|
||||
$validate = validate([$name => $this->rule]);
|
||||
if (!$validate->check([$name => $file])) {
|
||||
throw new \Exception($validate->getError());
|
||||
}
|
||||
|
||||
$fileName = $file->getOriginalName(); // 文件原名
|
||||
if (!$this->originalName) {
|
||||
$fileName = $this->buildFileName() . '.' . $file->extension();
|
||||
if (!$this->dir && !empty($this->pathPrefix)) {
|
||||
$fileName = $this->pathPrefix . '/' . $fileName;
|
||||
}
|
||||
}
|
||||
if ($this->dir) {
|
||||
$fileName = date('Y') . '/' . date('m') . '/' . date('d') . '/' . $fileName;
|
||||
if (!empty($this->pathPrefix)) {
|
||||
$fileName = $this->pathPrefix . '/' . $fileName;
|
||||
}
|
||||
}
|
||||
$filePath = $file->getPathname(); // 临时路径
|
||||
if (!empty($aspectRatio)) { // 验证图片宽高
|
||||
list($width, $height, $type, $attr) = getimagesize($file);
|
||||
if ($width != $aspectRatio['width'] || $height != $aspectRatio['height']) {
|
||||
throw new \Exception('图片宽高不符合');
|
||||
}
|
||||
}
|
||||
$fileType = $file->getOriginalMime();
|
||||
list($ret, $err) = $uploadMgr->putFile($token, $fileName, $filePath, null, $fileType, false);
|
||||
|
||||
if ($err !== null) {
|
||||
throw new \Exception($err);
|
||||
} else {
|
||||
return ['hash' => $ret['hash'], 'filename' => $ret['key'], 'remote_url' => self::$domain . $ret['key']];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 上传文件到七牛云
|
||||
*/
|
||||
public function deleteFile($name)
|
||||
{
|
||||
// 构建鉴权对象
|
||||
$auth = new Auth($this->accessKey, $this->secretKey);
|
||||
// 初始化 BucketManager 对象并进行文件的删除。
|
||||
$bucketManager = new BucketManager($auth);
|
||||
$ret = $bucketManager->delete($this->bucket, $name);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
78
extend/utils/BusinessDaysCalculator.php
Normal file
78
extend/utils/BusinessDaysCalculator.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
class BusinessDaysCalculator {
|
||||
|
||||
const MONDAY = 1;
|
||||
const TUESDAY = 2;
|
||||
const WEDNESDAY = 3;
|
||||
const THURSDAY = 4;
|
||||
const FRIDAY = 5;
|
||||
const SATURDAY = 6;
|
||||
const SUNDAY = 7;
|
||||
|
||||
private $date = '';
|
||||
|
||||
/**
|
||||
* @param DateTime $startDate Date to start calculations from
|
||||
* @param DateTime[] $holidays Array of holidays, holidays are no conisdered business days.
|
||||
* @param DateTime[] $nonBusinessDays Array of days of the week which are not business days.
|
||||
* @param DateTime[] $specialBusinessDay Array is the special work day.
|
||||
*/
|
||||
public function __construct(DateTime $startDate, array $holidays, array $nonBusinessDays ,array $specialBusinessDay) {
|
||||
$this->date = $startDate;
|
||||
$this->holidays=[];
|
||||
foreach($holidays as $holiday){
|
||||
array_push($this->holidays,new DateTime($holiday));
|
||||
}
|
||||
$this->nonBusinessDays = $nonBusinessDays;
|
||||
$this->specialBusinessDay = $specialBusinessDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指几个工作日后
|
||||
*/
|
||||
public function addBusinessDays($howManyDays) {
|
||||
$i = 0;
|
||||
while ($i < $howManyDays) {
|
||||
$this->date->modify("+1 day");
|
||||
if ($this->isBusinessDay($this->date)) {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getDate() {
|
||||
return $this->date->format('Y-m-d');
|
||||
}
|
||||
|
||||
private function isBusinessDay(DateTime $date) {
|
||||
if(in_array($date->format('Y-m-d') , $this->specialBusinessDay)) return true; // 判断当前日期是否是因法定节假日调休而上班的周末,这种情况也算工作日
|
||||
|
||||
if (in_array((int)$date->format('N'), $this->nonBusinessDays)) {
|
||||
return false; // 当前日期是周末
|
||||
}
|
||||
|
||||
foreach ($this->holidays as $day) {
|
||||
if ($date->format('Y-m-d') == $day->format('Y-m-d')) {
|
||||
return false; // 当前日期是法定节假日
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$holidays=["2017-01-27","2017-01-28","2017-01-29","2017-01-30","2017-01-31","2017-02-01","2017-02-02"]; // 从聚合数据接口获得
|
||||
$specialBusinessDay=["2017-01-22"]; // 因法定节假日调休而上班的周末,这种情况也算工作日.因为这种情况少,可以通过手动配置
|
||||
$calculator = new BusinessDaysCalculator(
|
||||
new DateTime(), // 当前时间
|
||||
$holidays,
|
||||
[BusinessDaysCalculator::SATURDAY, BusinessDaysCalculator::SUNDAY],
|
||||
$specialBusinessDay
|
||||
);
|
||||
|
||||
$calculator->addBusinessDays(2); // 2个工作日后的时间
|
||||
|
||||
$afterBusinessDay=$calculator->getDate();
|
||||
echo $afterBusinessDay;
|
||||
48
extend/utils/FileLog.php
Normal file
48
extend/utils/FileLog.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
class FileLog
|
||||
{
|
||||
private $filepath;
|
||||
|
||||
private $filename;
|
||||
|
||||
private $handle = null;
|
||||
|
||||
private $time;
|
||||
|
||||
public function __construct($filepath, $filename)
|
||||
{
|
||||
$this->time = date('Y-m-d H:i:s');
|
||||
$this->filepath = $filepath;
|
||||
$this->filename = $filename;
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
if (!is_dir($this->filepath))
|
||||
{
|
||||
mkdir($this->filepath, 0777, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function write($content, $type='err')
|
||||
{
|
||||
$str = $type . '=====';
|
||||
$str .= '当前时间为: ' . $this->time;
|
||||
$str .= '=====';
|
||||
$str .= $content . PHP_EOL;
|
||||
|
||||
if (substr($this->filepath, -1) == '/')
|
||||
{
|
||||
$file = $this->filepath . $this->filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $this->filepath . '/' . $this->filename;
|
||||
}
|
||||
|
||||
return file_put_contents($file, $str, FILE_APPEND);
|
||||
}
|
||||
|
||||
}
|
||||
168
extend/utils/Jwt.php
Normal file
168
extend/utils/Jwt.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace utils;
|
||||
|
||||
class Jwt
|
||||
{
|
||||
private $typ = 'JWT';
|
||||
|
||||
#key用户生成secret
|
||||
private $key = 'jSCq5heSuhDiuhSsad441wq6541SDA5415W6QE564dsda';
|
||||
|
||||
private $secret;
|
||||
|
||||
#加密算法
|
||||
private $alg = 'HS256';
|
||||
|
||||
#签发者-payload组成部分
|
||||
private $iss;
|
||||
|
||||
#过期时间-payload组成部分
|
||||
private $exp;
|
||||
|
||||
#签发时间-payload组成部分
|
||||
private $iat;
|
||||
|
||||
#用户基础信息-payload组成部分
|
||||
private $user_info;
|
||||
|
||||
#过期多久之前有效
|
||||
private $timeout = 7200;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->init();
|
||||
}
|
||||
|
||||
private function init()
|
||||
{
|
||||
$this->iss = $this->config['iss'];
|
||||
$this->exp = $this->config['exp'];
|
||||
$this->iat = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
* @param array $user_info
|
||||
* @return string
|
||||
*/
|
||||
public function getToken(array $user_info):string
|
||||
{
|
||||
//头信息
|
||||
$header = [
|
||||
'typ' => $this->typ,
|
||||
'alg' => $this->alg
|
||||
];
|
||||
$base64_header = base64_encode(json_encode($header));
|
||||
|
||||
//有效载荷
|
||||
$payload = [
|
||||
'iss' => $this->iss,
|
||||
'exp' => $this->exp,
|
||||
'iat' => $this->iat,
|
||||
'user_info' => $user_info,
|
||||
];
|
||||
$base64_payload = base64_encode(json_encode($payload));
|
||||
|
||||
//签名信息
|
||||
$this->secret = $this->getSecret($user_info);
|
||||
$signature = $base64_header . $base64_payload . $this->secret;
|
||||
$base64_signature = $this->enc($this->alg, $signature);
|
||||
|
||||
$jwt_token = $base64_header . '.' . $base64_payload . '.' . $base64_signature;
|
||||
return $jwt_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验token
|
||||
* @param $jwt_token
|
||||
* @return int
|
||||
*/
|
||||
public function checkToken($jwt_token)
|
||||
{
|
||||
$arr = explode('.', $jwt_token);
|
||||
if (count($arr) < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
$base64_header = $arr[0];
|
||||
$base64_payload = $arr[1];
|
||||
$base64_signature = $arr[2];
|
||||
|
||||
$payload = json_decode(base64_decode($base64_payload), true);
|
||||
if (!is_array($payload) || !isset($payload['exp']) || !isset($payload['iat']) || !isset($payload['user_info'])) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
//生成签名,比较
|
||||
$this->secret = $this->getSecret($payload['user_info']);
|
||||
$tmp_signature = $base64_header . $base64_payload . $this->secret;
|
||||
$tmp_base64_signature = $this->enc($this->alg, $tmp_signature);
|
||||
|
||||
if ($base64_signature !== $tmp_base64_signature) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
// 是否过期
|
||||
if ($payload['exp'] + $payload['iat'] - time() < 0) {
|
||||
// token过期了
|
||||
return -4;
|
||||
} else {
|
||||
// token没有过期
|
||||
if ($payload['exp'] + $payload['iat'] - time() - $this->timeout < 0) {
|
||||
return 201;
|
||||
}
|
||||
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param $jwt_token
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getUserInfo($jwt_token)
|
||||
{
|
||||
$arr = explode('.', $jwt_token);
|
||||
if (count($arr) < 3) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$base64_payload = $arr[1];
|
||||
|
||||
$payload = json_decode(base64_decode($base64_payload), true);
|
||||
if (!is_array($payload) || !isset($payload['user_info'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $payload['user_info'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取secret,保证每个用户的secret都不同
|
||||
* @param $user_info
|
||||
* @return string
|
||||
*/
|
||||
private function getSecret($user_info)
|
||||
{
|
||||
return md5($this->key . json_encode($user_info));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* @param $enc_type
|
||||
* @param $content
|
||||
* @return string
|
||||
*/
|
||||
private function enc($enc_type, $content)
|
||||
{
|
||||
if ($enc_type == 'HS256')
|
||||
{
|
||||
return hash('sha256', $content);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
87
extend/utils/Mailer.php
Normal file
87
extend/utils/Mailer.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
namespace utils;
|
||||
|
||||
require_once root_path() . '/vendor/phpmailer/class.phpmailer.php';
|
||||
require_once root_path() . '/vendor/phpmailer/class.smtp.php';
|
||||
|
||||
use PHPMailer;
|
||||
|
||||
class Mailer
|
||||
{
|
||||
const CHARTSET = 'UTF-8';
|
||||
const PORT = 456;
|
||||
const HOST = 'smtp.qq.com';
|
||||
private $username = '735273025@qq.com';
|
||||
private $password = 'gtxknrzhmctlbbfb';
|
||||
|
||||
private $fromAccount = '735273025@qq.com';
|
||||
private $fromName = 'Jsasg';
|
||||
private $toAccount = '735273025@qq.com';
|
||||
private $toName = 'Jsasg';
|
||||
|
||||
private $subject = '';
|
||||
private $body = '';
|
||||
private $altBody = '';
|
||||
|
||||
/**
|
||||
* 设置主题
|
||||
* @param string $subject
|
||||
*/
|
||||
public function setSubject($subject)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置内容
|
||||
* @param string $body
|
||||
*/
|
||||
public function setBody($body)
|
||||
{
|
||||
$this->body = $body;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置不支持html时的内容
|
||||
* @param string $string 内容
|
||||
*/
|
||||
public function setAltBody($string)
|
||||
{
|
||||
$this->altBody = $string;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
$success = false;
|
||||
$mail = new PHPMailer(true);
|
||||
try {
|
||||
$mail->CharSet = self::CHARTSET; //设定邮件编码
|
||||
$mail->SMTPDebug = 0; // 调试模式输出
|
||||
$mail->isSMTP(); // 使用SMTP
|
||||
$mail->Host = self::HOST; // SMTP服务器
|
||||
$mail->SMTPAuth = true; // 允许 SMTP 认证
|
||||
$mail->Username = $this->username; // SMTP 用户名 即邮箱的用户名
|
||||
$mail->Password = $this->password; // SMTP 密码 部分邮箱是授权码(例如163邮箱)
|
||||
$mail->SMTPSecure = 'ssl'; // 允许 TLS 或者ssl协议
|
||||
$mail->Port = 465; // 服务器端口 25 或者 465 具体要看邮箱服务器支持
|
||||
|
||||
$mail->setFrom($this->fromAccount, $this->fromName); //发件人
|
||||
$mail->addAddress($this->toAccount, $this->toName); // 收件人
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $this->subject;
|
||||
$mail->Body = $this->body;
|
||||
$mail->AltBody = $this->altBody;
|
||||
|
||||
$success = $mail->send();
|
||||
} catch (\Exception $error) {
|
||||
exit($mail->ErrorInfo);
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
148
extend/utils/OrederStatusSync4Redis.php
Normal file
148
extend/utils/OrederStatusSync4Redis.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
namespace utils;
|
||||
use think\cache\driver\Redis;
|
||||
use think\facade\Config;
|
||||
|
||||
class OrederStatusSync4Redis
|
||||
{
|
||||
private $client;
|
||||
private $key;
|
||||
private $group;
|
||||
private $consumer;
|
||||
|
||||
public function __construct($config=[])
|
||||
{
|
||||
$this->key = Config::get('redis.erp.order_sync_stream.key');
|
||||
if (empty($this->key)) {
|
||||
throw new \Exception('未配置默认STREAM标识key');
|
||||
}
|
||||
$this->group = Config::get('redis.erp.order_sync_stream.group');
|
||||
if (empty($this->group)) {
|
||||
throw new \Exception('未配置默认STREAM消费者组');
|
||||
}
|
||||
$this->consumer = Config::get('redis.erp.order_sync_stream.consumer');
|
||||
if (empty($this->consumer)) {
|
||||
throw new \Exception('未配置默认STREAM消费者');
|
||||
}
|
||||
if (empty($config)) {
|
||||
$config = Config::get('redis.erp.conf');
|
||||
}
|
||||
$this->client = new Redis($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key 设置stream标识key
|
||||
*/
|
||||
public function streamKey($key)
|
||||
{
|
||||
if (empty($key)) {
|
||||
return false;
|
||||
}
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $group 设置消费者组
|
||||
*/
|
||||
public function streamGroup($group)
|
||||
{
|
||||
if (empty($group)) {
|
||||
return false;
|
||||
}
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $consumer 设置消费者
|
||||
*/
|
||||
public function streamConsumer($consumer)
|
||||
{
|
||||
if (empty($consumer)) {
|
||||
return false;
|
||||
}
|
||||
$this->consumer = $consumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否存在消息组
|
||||
* @param string $streamGroup 消费者组
|
||||
* @return bool
|
||||
*/
|
||||
public function hasGroup($streamGroup='')
|
||||
{
|
||||
$groups = $this->client->xInfo('GROUPS', $this->key);
|
||||
if (empty($groups)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($streamGroup)) {
|
||||
$streamGroup = $this->group; // 使用配置的消费组
|
||||
}
|
||||
if (!in_array($streamGroup, array_column($groups, 'name'))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建消息组
|
||||
* @param string $streamGroup 消费者组
|
||||
* @param string $msgID 0为查看所有消息,$为查看最新消息
|
||||
*/
|
||||
public function createGroup($streamGroup='', $msgID='0')
|
||||
{
|
||||
if (empty($streamGroup)) {
|
||||
$streamGroup = $this->group; // 使用配置的消费组
|
||||
}
|
||||
$this->client->xGroup('CREATE', $this->key, $streamGroup, $msgID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取新消息
|
||||
* @param int $count 获取条数
|
||||
* @param int $block 是否阻塞:0为永久阻塞,null为不阻塞,1000为阻塞1秒
|
||||
* @return array
|
||||
*/
|
||||
public function fetchMessage($count=null, $block=null)
|
||||
{
|
||||
$keys[$this->key] = '>'; // 获取新消息
|
||||
$messages = $this->client->xReadGroup($this->group, $this->consumer, $keys, $count, $block);
|
||||
return !empty($messages) ? $messages[$this->key] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未处理消费
|
||||
* @param int $count 获取条数
|
||||
* @param int $block 是否阻塞:0为永久阻塞,null为不阻塞,1000为阻塞1秒
|
||||
* @return array
|
||||
*/
|
||||
public function fetchMessage4UnAck($count=null, $block=null)
|
||||
{
|
||||
$keys[$this->key] = '0'; // 获取未处理的
|
||||
$messages = $this->client->xReadGroup($this->group, $this->consumer, $keys, $count, $block);
|
||||
return !empty($messages) ? $messages[$this->key] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取处理PENDING中消息
|
||||
* @param int $count 获取条数
|
||||
* @return array
|
||||
*/
|
||||
public function fetchMessage4Pending($count = 10)
|
||||
{
|
||||
$messages = $this->client->xPending($this->key, $this->group, '-', '+', $count, $this->consumer);
|
||||
return !empty($messages) ? $messages : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据消息ID设为消息已处理
|
||||
* @param array|string 消息ID
|
||||
* @param int 处理系数
|
||||
*/
|
||||
public function ack($messagesID)
|
||||
{
|
||||
if (!is_array($messagesID)) {
|
||||
$messagesID = [$messagesID];
|
||||
}
|
||||
return $this->client->xAck($this->key, $this->group, $messagesID);
|
||||
}
|
||||
}
|
||||
200
extend/utils/QiniuUploader.php
Normal file
200
extend/utils/QiniuUploader.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
namespace utils;
|
||||
|
||||
use think\facade\Env;
|
||||
use Qiniu\Auth;
|
||||
use Qiniu\Storage\UploadManager;
|
||||
|
||||
/**
|
||||
* 七牛云上传
|
||||
* Class QiniuUploader
|
||||
* @package utils
|
||||
*/
|
||||
class QiniuUploader
|
||||
{
|
||||
protected $bucket = 'orico-cms';
|
||||
protected $accessKey = 'dOsTum4a5qvhPTBbZRPX0pIOU7PZWRX7htKjztms';
|
||||
protected $secretKey = 'KFxsGbnErkALFfeGdMa8QWTdodJbamMX0iznLe-q';
|
||||
|
||||
protected $rule = [
|
||||
'fileSize' => 1024 * 1024 * 5, // 默认最大上传5M
|
||||
'fileExt' => 'jpeg,jpg,png', // 默认上传文件后缀
|
||||
'fileMime' => 'image/jpeg,image/png,image/gif' // 默认上传文件mime
|
||||
];
|
||||
|
||||
protected $dir = true;
|
||||
protected $originalName = false;
|
||||
protected $pathPrefix = '';
|
||||
protected $fileNamePrefix = 'cms_';
|
||||
|
||||
protected $domain = '';
|
||||
|
||||
public function __construct($conf = [])
|
||||
{
|
||||
$this->domain = Env::get("QINIU.cdn");
|
||||
if (!empty($conf['bucket'])) {
|
||||
$this->bucket = $conf['bucket'];
|
||||
}
|
||||
if (!empty($conf['accessKey'])) {
|
||||
$this->accessKey = $conf['accessKey'];
|
||||
}
|
||||
if (!empty($conf['secretKey'])) {
|
||||
$this->secretKey = $conf['secretKey'];
|
||||
}
|
||||
if (!empty($conf['pathPrefix'])) {
|
||||
$this->pathPrefix = trim($conf['pathPrefix'], '/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机字符串
|
||||
*/
|
||||
private function random($length, $type="string", $convert="0")
|
||||
{
|
||||
$conf = [
|
||||
'number' => '0123456789',
|
||||
'string' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789='
|
||||
];
|
||||
$string = $conf[$type];
|
||||
if(!$string) {
|
||||
$string = $conf['string'];
|
||||
}
|
||||
$strlen = strlen($string) - 1;
|
||||
$char = '';
|
||||
for($i=0; $i<$length; $i++) {
|
||||
$char .= $string[mt_rand(0, $strlen)];
|
||||
}
|
||||
if($convert > 0) {
|
||||
$res = strtoupper($char);
|
||||
} elseif ($convert == 0) {
|
||||
$res = $char;
|
||||
} elseif ($convert < 0) {
|
||||
$res = strtolower($char);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装文件名
|
||||
*/
|
||||
private function buildFileName()
|
||||
{
|
||||
return $this->fileNamePrefix . time().substr(time(),-5).substr(microtime(),2,3) . $this->random(8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传验证规则
|
||||
*/
|
||||
public function validate($rule)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到七牛云
|
||||
* @param $name
|
||||
* @param bool $multi 多文件模式
|
||||
* @param int $num 多文件模式文件数量
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function uploadFile($name,$multi=false,$num = 1)
|
||||
{
|
||||
// 构建鉴权对象
|
||||
$auth = new Auth($this->accessKey, $this->secretKey);
|
||||
|
||||
// 生成上传 Token
|
||||
$token = $auth->uploadToken($this->bucket);
|
||||
|
||||
// 初始化 UploadManager 对象并进行文件的上传。
|
||||
$uploadMgr = new UploadManager();
|
||||
|
||||
$data = [];
|
||||
if (false === $multi) {
|
||||
$file = request()->file($name);
|
||||
$data = $this->doFileToQn($file, $uploadMgr, $token);
|
||||
} else {
|
||||
for ($i = 0; $i < $num; $i++) {
|
||||
$file = request()->file($name)[$i];
|
||||
$data[] = $this->doFileToQn($file, $uploadMgr, $token);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 七牛云上传本地文件,并且本地相对路由和七牛云路径完全一致
|
||||
* @param string $fullName 文件名称带全路径。/www/wwwroot/test.yulinzhihou.com/public/ueditor/php/upload/file/20210424/1619232876970230.png
|
||||
* @param string $relativePath 相对路径,注意:前面不能以斜杠开头 如:ueditor/php/upload/file/20210424/1619232876970230.png
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function uploadLocalFile($fullName,$relativePath)
|
||||
{
|
||||
// 构建鉴权对象
|
||||
$auth = new Auth($this->accessKey, $this->secretKey);
|
||||
// 生成上传 Token
|
||||
$token = $auth->uploadToken($this->bucket);
|
||||
// 初始化 UploadManager 对象并进行文件的上传。
|
||||
$uploadMgr = new UploadManager();
|
||||
$file = ltrim($relativePath,'\/');
|
||||
list($ret, $err) = $uploadMgr->putFile($token,$file,$fullName);
|
||||
if ($err !== null) {
|
||||
throw new \Exception($err);
|
||||
} else {
|
||||
return ['hash'=>$ret['hash'], 'filename'=>$ret['key'], 'remote_url'=>$this->domain . $ret['key']];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @param UploadManager $uploadMgr
|
||||
* @param string $token
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function doFileToQn($file, UploadManager $uploadMgr, string $token): array
|
||||
{
|
||||
$aspectRatio = [];
|
||||
if (!empty($this->rule['aspectRatio'])) {
|
||||
$aspectRatio = $this->rule['aspectRatio'];
|
||||
unset($this->rule['aspectRatio']);
|
||||
}
|
||||
|
||||
$fileName = $file->getOriginalName(); // 文件原名
|
||||
|
||||
if (!$this->originalName) {
|
||||
$fileName = $this->buildFileName() . '.' . $file->extension();
|
||||
if (!$this->dir && !empty($this->pathPrefix)) {
|
||||
$fileName = $this->pathPrefix . '/' . $fileName;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->dir) {
|
||||
$fileName = date('Y') . '/' . date('m') . '/' . date('d') . '/' . $fileName;
|
||||
if (!empty($this->pathPrefix)) {
|
||||
$fileName = $this->pathPrefix . '/' . $fileName;
|
||||
}
|
||||
}
|
||||
|
||||
$filePath = $file->getPathname(); // 临时路径
|
||||
if (!empty($aspectRatio)) { // 验证图片宽高
|
||||
list($width, $height, $type, $attr) = getimagesize($file);
|
||||
if ($width != $aspectRatio['width'] || $height != $aspectRatio['height']) {
|
||||
throw new \Exception('图片宽高不符合');
|
||||
}
|
||||
}
|
||||
$fileType = $file->getOriginalMime();
|
||||
list($ret, $err) = $uploadMgr->putFile($token, $fileName, $filePath, null, $fileType, false);
|
||||
if ($err !== null) {
|
||||
throw new \Exception($err);
|
||||
} else {
|
||||
return ['hash' => $ret['hash'], 'filename' => $ret['key'], 'remote_url' => $this->domain . $ret['key']];
|
||||
}
|
||||
}
|
||||
}
|
||||
371
extend/utils/UEUploader.php
Normal file
371
extend/utils/UEUploader.php
Normal file
@@ -0,0 +1,371 @@
|
||||
<?php
|
||||
namespace utils;
|
||||
/**
|
||||
* Created by JetBrains PhpStorm.
|
||||
* User: taoqili
|
||||
* Date: 12-7-18
|
||||
* Time: 上午11: 32
|
||||
* UEditor编辑器通用上传类
|
||||
*/
|
||||
class UEUploader
|
||||
{
|
||||
private $fileField; //文件域名
|
||||
private $file; //文件上传对象
|
||||
private $base64; //文件上传对象
|
||||
private $config; //配置信息
|
||||
private $oriName; //原始文件名
|
||||
private $fileName; //新文件名
|
||||
private $fullName; //完整文件名,即从当前配置目录开始的URL
|
||||
private $filePath; //完整文件名,即从当前配置目录开始的URL
|
||||
private $fileSize; //文件大小
|
||||
private $fileType; //文件类型
|
||||
private $stateInfo; //上传状态信息,
|
||||
private $stateMap = array( //上传状态映射表,国际化用户需考虑此处数据的国际化
|
||||
"SUCCESS", //上传成功标记,在UEditor中内不可改变,否则flash判断会出错
|
||||
"文件大小超出 upload_max_filesize 限制",
|
||||
"文件大小超出 MAX_FILE_SIZE 限制",
|
||||
"文件未被完整上传",
|
||||
"没有文件被上传",
|
||||
"上传文件为空",
|
||||
"ERROR_TMP_FILE" => "临时文件错误",
|
||||
"ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件",
|
||||
"ERROR_SIZE_EXCEED" => "文件大小超出网站限制",
|
||||
"ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许",
|
||||
"ERROR_CREATE_DIR" => "目录创建失败",
|
||||
"ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限",
|
||||
"ERROR_FILE_MOVE" => "文件保存时出错",
|
||||
"ERROR_FILE_NOT_FOUND" => "找不到上传文件",
|
||||
"ERROR_WRITE_CONTENT" => "写入文件内容错误",
|
||||
"ERROR_UNKNOWN" => "未知错误",
|
||||
"ERROR_DEAD_LINK" => "链接不可用",
|
||||
"ERROR_HTTP_LINK" => "链接不是http链接",
|
||||
"ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确",
|
||||
"INVALID_URL" => "非法 URL",
|
||||
"INVALID_IP" => "非法 IP"
|
||||
);
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param string $fileField 表单名称
|
||||
* @param array $config 配置项
|
||||
* @param bool $base64 是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名
|
||||
*/
|
||||
public function __construct($fileField, $config, $type = "upload")
|
||||
{
|
||||
$this->fileField = $fileField;
|
||||
$this->config = $config;
|
||||
$this->type = $type;
|
||||
if ($type == "remote") {
|
||||
$this->saveRemote();
|
||||
} else if($type == "base64") {
|
||||
$this->upBase64();
|
||||
} else {
|
||||
$this->upFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件的主处理方法
|
||||
* @return mixed
|
||||
*/
|
||||
private function upFile()
|
||||
{
|
||||
$file = $this->file = $_FILES[$this->fileField];
|
||||
if (!$file) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND");
|
||||
return;
|
||||
}
|
||||
if ($this->file['error']) {
|
||||
$this->stateInfo = $this->getStateInfo($file['error']);
|
||||
return;
|
||||
} else if (!file_exists($file['tmp_name'])) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND");
|
||||
return;
|
||||
} else if (!is_uploaded_file($file['tmp_name'])) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_TMPFILE");
|
||||
return;
|
||||
}
|
||||
|
||||
$this->oriName = $file['name'];
|
||||
$this->fileSize = $file['size'];
|
||||
$this->fileType = $this->getFileExt();
|
||||
$this->fullName = $this->getFullName();
|
||||
$this->filePath = $this->getFilePath();
|
||||
$this->fileName = $this->getFileName();
|
||||
$dirname = dirname($this->filePath);
|
||||
|
||||
//检查文件大小是否超出限制
|
||||
if (!$this->checkSize()) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
|
||||
return;
|
||||
}
|
||||
|
||||
//检查是否不允许的文件格式
|
||||
if (!$this->checkType()) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED");
|
||||
return;
|
||||
}
|
||||
|
||||
//创建目录失败
|
||||
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
|
||||
return;
|
||||
} else if (!is_writeable($dirname)) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
|
||||
return;
|
||||
}
|
||||
|
||||
//移动文件
|
||||
if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) {
|
||||
//移动失败
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE");
|
||||
} else {
|
||||
//移动成功
|
||||
$this->stateInfo = $this->stateMap[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理base64编码的图片上传
|
||||
* @return mixed
|
||||
*/
|
||||
private function upBase64()
|
||||
{
|
||||
$base64Data = $_POST[$this->fileField];
|
||||
$img = base64_decode($base64Data);
|
||||
|
||||
$this->oriName = $this->config['oriName'];
|
||||
$this->fileSize = strlen($img);
|
||||
$this->fileType = $this->getFileExt();
|
||||
$this->fullName = $this->getFullName();
|
||||
$this->filePath = $this->getFilePath();
|
||||
$this->fileName = $this->getFileName();
|
||||
$dirname = dirname($this->filePath);
|
||||
|
||||
//检查文件大小是否超出限制
|
||||
if (!$this->checkSize()) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
|
||||
return;
|
||||
}
|
||||
|
||||
//创建目录失败
|
||||
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
|
||||
return;
|
||||
} else if (!is_writeable($dirname)) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
|
||||
return;
|
||||
}
|
||||
|
||||
//移动文件
|
||||
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
|
||||
} else { //移动成功
|
||||
$this->stateInfo = $this->stateMap[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取远程图片
|
||||
* @return mixed
|
||||
*/
|
||||
private function saveRemote()
|
||||
{
|
||||
$imgUrl = htmlspecialchars($this->fileField);
|
||||
$imgUrl = str_replace("&", "&", $imgUrl);
|
||||
|
||||
//http开头验证
|
||||
if (strpos($imgUrl, "http") !== 0) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
|
||||
return;
|
||||
}
|
||||
|
||||
preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);
|
||||
$host_with_protocol = count($matches) > 1 ? $matches[1] : '';
|
||||
|
||||
// 判断是否是合法 url
|
||||
if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
|
||||
$this->stateInfo = $this->getStateInfo("INVALID_URL");
|
||||
return;
|
||||
}
|
||||
|
||||
preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
|
||||
$host_without_protocol = count($matches) > 1 ? $matches[1] : '';
|
||||
|
||||
// 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
|
||||
$ip = gethostbyname($host_without_protocol);
|
||||
// 判断是否是私有 ip
|
||||
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||
$this->stateInfo = $this->getStateInfo("INVALID_IP");
|
||||
return;
|
||||
}
|
||||
|
||||
//获取请求头并检测死链
|
||||
$heads = get_headers($imgUrl, 1);
|
||||
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
|
||||
return;
|
||||
}
|
||||
//格式验证(扩展名验证和Content-Type验证)
|
||||
$fileType = strtolower(strrchr($imgUrl, '.'));
|
||||
if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
|
||||
return;
|
||||
}
|
||||
|
||||
//打开输出缓冲区并获取远程图片
|
||||
ob_start();
|
||||
$context = stream_context_create(
|
||||
array('http' => array(
|
||||
'follow_location' => false // don't follow redirects
|
||||
))
|
||||
);
|
||||
readfile($imgUrl, false, $context);
|
||||
$img = ob_get_contents();
|
||||
ob_end_clean();
|
||||
preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
|
||||
|
||||
$this->oriName = $m ? $m[1]:"";
|
||||
$this->fileSize = strlen($img);
|
||||
$this->fileType = $this->getFileExt();
|
||||
$this->fullName = $this->getFullName();
|
||||
$this->filePath = $this->getFilePath();
|
||||
$this->fileName = $this->getFileName();
|
||||
$dirname = dirname($this->filePath);
|
||||
|
||||
//检查文件大小是否超出限制
|
||||
if (!$this->checkSize()) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
|
||||
return;
|
||||
}
|
||||
|
||||
//创建目录失败
|
||||
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
|
||||
return;
|
||||
} else if (!is_writeable($dirname)) {
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
|
||||
return;
|
||||
}
|
||||
|
||||
//移动文件
|
||||
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
|
||||
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
|
||||
} else { //移动成功
|
||||
$this->stateInfo = $this->stateMap[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传错误检查
|
||||
* @param $errCode
|
||||
* @return string
|
||||
*/
|
||||
private function getStateInfo($errCode)
|
||||
{
|
||||
return !$this->stateMap[$errCode] ? $this->stateMap["ERROR_UNKNOWN"] : $this->stateMap[$errCode];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件扩展名
|
||||
* @return string
|
||||
*/
|
||||
private function getFileExt()
|
||||
{
|
||||
return strtolower(strrchr($this->oriName, '.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名文件
|
||||
* @return string
|
||||
*/
|
||||
private function getFullName()
|
||||
{
|
||||
//替换日期事件
|
||||
$t = time();
|
||||
$d = explode('-', date("Y-y-m-d-H-i-s"));
|
||||
$format = $this->config["pathFormat"];
|
||||
$format = str_replace("{yyyy}", $d[0], $format);
|
||||
$format = str_replace("{yy}", $d[1], $format);
|
||||
$format = str_replace("{mm}", $d[2], $format);
|
||||
$format = str_replace("{dd}", $d[3], $format);
|
||||
$format = str_replace("{hh}", $d[4], $format);
|
||||
$format = str_replace("{ii}", $d[5], $format);
|
||||
$format = str_replace("{ss}", $d[6], $format);
|
||||
$format = str_replace("{time}", $t, $format);
|
||||
|
||||
//过滤文件名的非法自负,并替换文件名
|
||||
$oriName = substr($this->oriName, 0, strrpos($this->oriName, '.'));
|
||||
$oriName = preg_replace("/[\|\?\"\<\>\/\*\\\\]+/", '', $oriName);
|
||||
$format = str_replace("{filename}", $oriName, $format);
|
||||
|
||||
//替换随机字符串
|
||||
$randNum = rand(1, 10000000000) . rand(1, 10000000000);
|
||||
if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) {
|
||||
$format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format);
|
||||
}
|
||||
|
||||
$ext = $this->getFileExt();
|
||||
return $format . $ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件名
|
||||
* @return string
|
||||
*/
|
||||
private function getFileName () {
|
||||
return substr($this->filePath, strrpos($this->filePath, '/') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件完整路径
|
||||
* @return string
|
||||
*/
|
||||
private function getFilePath()
|
||||
{
|
||||
$fullname = $this->fullName;
|
||||
$rootPath = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
if (substr($fullname, 0, 1) != '/') {
|
||||
$fullname = '/' . $fullname;
|
||||
}
|
||||
return $rootPath . $fullname;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件类型检测
|
||||
* @return bool
|
||||
*/
|
||||
private function checkType()
|
||||
{
|
||||
return in_array($this->getFileExt(), $this->config["allowFiles"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件大小检测
|
||||
* @return bool
|
||||
*/
|
||||
private function checkSize()
|
||||
{
|
||||
return $this->fileSize <= ($this->config["maxSize"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前上传成功文件的各项信息
|
||||
* @return array
|
||||
*/
|
||||
public function getFileInfo()
|
||||
{
|
||||
return array(
|
||||
"state" => $this->stateInfo,
|
||||
"url" => $this->fullName,
|
||||
"title" => $this->fileName,
|
||||
"original" => $this->oriName,
|
||||
"type" => $this->fileType,
|
||||
"size" => $this->fileSize
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
146
extend/utils/UnionpayB2C.php
Normal file
146
extend/utils/UnionpayB2C.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* unionpay在线网关支付B2C业务
|
||||
*/
|
||||
class UnionpayB2C
|
||||
{
|
||||
protected $pay_type = 'unionpay_b2c';
|
||||
|
||||
#版本号
|
||||
protected $version;
|
||||
|
||||
#编码方式
|
||||
protected $encoding = 'UTF-8';
|
||||
|
||||
#交易币种列表
|
||||
protected $currencyCode_list = [
|
||||
'CNY' => '156'
|
||||
];
|
||||
|
||||
protected $currencyCode;
|
||||
|
||||
#交易子类型列表,支付接口专用
|
||||
protected $txnSubType_list = [
|
||||
'zizhu' => '01',
|
||||
'fenqi' => '03',
|
||||
];
|
||||
|
||||
protected $txnSubType;
|
||||
|
||||
#接入类型
|
||||
protected $accessType = '0'; //商户直连
|
||||
|
||||
#签名算法
|
||||
protected $signMethod;
|
||||
|
||||
#渠道类型列表
|
||||
protected $channelType_list = [
|
||||
'pc' => '07',
|
||||
'mobile' => '08'
|
||||
];
|
||||
|
||||
protected $channelType;
|
||||
|
||||
#商户号
|
||||
// protected $merId = '777290058181532'; //test
|
||||
protected $merId = '802310057320534'; //线上
|
||||
|
||||
#接口url列表
|
||||
protected $dev_url_list = [
|
||||
'pay' => 'https://gateway.test.95516.com/gateway/api/frontTransReq.do',
|
||||
'query' => 'https://gateway.test.95516.com/gateway/api/queryTrans.do',
|
||||
];
|
||||
|
||||
protected $prod_url_list = [
|
||||
'pay' => 'https://gateway.95516.com/gateway/api/frontTransReq.do',
|
||||
'query' => 'https://gateway.95516.com/gateway/api/queryTrans.do',
|
||||
];
|
||||
|
||||
protected $url_list;
|
||||
|
||||
private $logger;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化部分参数
|
||||
*/
|
||||
private function init()
|
||||
{
|
||||
require_once app()->getRootPath() . '/extend/payment/unionpay/sdk/AcpService.php';
|
||||
$this->version = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->version;
|
||||
$this->front_url = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->frontUrl;
|
||||
$this->back_url = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->backUrl;
|
||||
$this->signMethod = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->signMethod;
|
||||
// $this->url_list = $this->dev_url_list;
|
||||
$this->url_list = $this->prod_url_list;
|
||||
|
||||
$date = explode('-', date('Y-m-d'));
|
||||
$filepath = APP_PATH . 'Lib/pay/log/' . $date[0] . '-' . $date[1] . '/' . $date[2];
|
||||
$filename = $this->pay_type . '.log';
|
||||
import('ORG.Util.FileLog');
|
||||
$this->logger = new FileLog($filepath, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付状态
|
||||
* @param $pay_log === pay_log表记录
|
||||
*/
|
||||
public function query($pay_log)
|
||||
{
|
||||
$out_trade_no = $pay_log['out_trade_no'];
|
||||
$txnTime = date('YmdHis', strtotime($pay_log['create_time']));
|
||||
$this->bizType = $this->bizType_list['query'][$pay_log['pay_type']];
|
||||
$this->channelType = $this->channelType_list[$pay_log['source']];
|
||||
$params = [
|
||||
'version' => $this->version, //版本号
|
||||
'encoding' => $this->encoding, //编码方式
|
||||
'signMethod' => $this->signMethod, //签名方法
|
||||
'txnType' => '00', //交易类型
|
||||
'txnSubType' => '00', //交易子类
|
||||
'bizType' => '000000', //业务类型
|
||||
'accessType' => $this->accessType, //接入类型
|
||||
'channelType' => $this->channelType, //渠道类型
|
||||
|
||||
'orderId' => $out_trade_no, //请修改被查询的交易的订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数
|
||||
'merId' => $this->merId, //商户代码,请改自己的测试商户号,此处默认取demo演示页面传递的参数
|
||||
'txnTime' => $txnTime, //请修改被查询的交易的订单发送时间,格式为YYYYMMDDhhmmss,此处默认取demo演示页面传递的参数
|
||||
];
|
||||
|
||||
com\unionpay\acp\sdk\AcpService::sign ( $params ); // 签名
|
||||
$url = $this->url_list['query'];
|
||||
|
||||
$this->logger->write('查询请求参数: ' . json_encode($params) . '=====url: ' . $url, 'suc');
|
||||
$result_arr = com\unionpay\acp\sdk\AcpService::post ( $params, $url);
|
||||
|
||||
if (count($result_arr) > 0 &&
|
||||
com\unionpay\acp\sdk\AcpService::validate ($result_arr) &&
|
||||
$result_arr["respCode"] == "00" &&
|
||||
$result_arr["origRespCode"] == "00"
|
||||
)
|
||||
{
|
||||
$this->logger->write('查询完成,交易成功,交易单号: ' . $out_trade_no, 'suc');
|
||||
return $result_arr;
|
||||
}
|
||||
|
||||
$this->logger->write('查询完成,交易失败,交易单号: ' . $out_trade_no);
|
||||
return false;
|
||||
}
|
||||
|
||||
private function http_success()
|
||||
{
|
||||
header("HTTP/1.1 200 OK");
|
||||
exit;
|
||||
}
|
||||
|
||||
private function http_fail()
|
||||
{
|
||||
header("HTTP/1.1 500 ERROR");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
68
extend/utils/WorkingDay.php
Normal file
68
extend/utils/WorkingDay.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace utils;
|
||||
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 获取工作日
|
||||
*/
|
||||
class WorkingDay
|
||||
{
|
||||
private $time = 0;
|
||||
private $holidays = [];
|
||||
public function __construct($time=0)
|
||||
{
|
||||
if (empty($time)) $this->time = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前年度的节假日
|
||||
*/
|
||||
private function getHolidays()
|
||||
{
|
||||
$data = Db::name('holiday')->where('year', '=', date('Y'))->column('data');
|
||||
if (empty($data)) {
|
||||
$this->holidays = [];
|
||||
}
|
||||
$this->holidays = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取工作日
|
||||
*/
|
||||
public function getDates($adays)
|
||||
{
|
||||
// 获取节假日
|
||||
$this->getHolidays();
|
||||
|
||||
// 组装工作日
|
||||
$ctime = $this->time;
|
||||
$days = [];
|
||||
$i = 1;
|
||||
while($adays>0) {
|
||||
$day = strtotime("+ $i day", $ctime);
|
||||
$week = date('w', $day);
|
||||
// 剔除周六周日与假日
|
||||
if (0 != $week && 6 != $week && !in_array(date('Y-m-d', $day), $this->holidays)) {
|
||||
$adays-=1;
|
||||
$days[] = date('Y-m-d H:i:s', $day);
|
||||
}
|
||||
$i+=1;
|
||||
}
|
||||
return $days;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取几个工作日后日期
|
||||
*/
|
||||
public function getDate($adays, $ctime = 0)
|
||||
{
|
||||
if (!empty($ctime)) {
|
||||
$this->time = $ctime;
|
||||
}
|
||||
$days = $this->getDates($adays);
|
||||
rsort($days);
|
||||
return $days[0];
|
||||
}
|
||||
}
|
||||
|
||||
94
extend/utils/ueditor_config.json
Normal file
94
extend/utils/ueditor_config.json
Normal file
@@ -0,0 +1,94 @@
|
||||
/* 前后端通信相关的配置,注释只允许使用多行方式 */
|
||||
{
|
||||
/* 上传图片配置项 */
|
||||
"imageActionName": "uploadimage", /* 执行上传图片的action名称 */
|
||||
"imageFieldName": "upfile", /* 提交的图片表单名称 */
|
||||
"imageMaxSize": 20480000, /* 上传大小限制,单位B */
|
||||
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
|
||||
"imageCompressEnable": true, /* 是否压缩图片,默认是true */
|
||||
"imageCompressBorder": 1600, /* 图片压缩最长边限制 */
|
||||
"imageInsertAlign": "none", /* 插入的图片浮动方式 */
|
||||
"imageUrlPrefix": "", /* 图片访问路径前缀 */
|
||||
"imagePathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
||||
/* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
|
||||
/* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
|
||||
/* {time} 会替换成时间戳 */
|
||||
/* {yyyy} 会替换成四位年份 */
|
||||
/* {yy} 会替换成两位年份 */
|
||||
/* {mm} 会替换成两位月份 */
|
||||
/* {dd} 会替换成两位日期 */
|
||||
/* {hh} 会替换成两位小时 */
|
||||
/* {ii} 会替换成两位分钟 */
|
||||
/* {ss} 会替换成两位秒 */
|
||||
/* 非法字符 \ : * ? " < > | */
|
||||
/* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
|
||||
|
||||
/* 涂鸦图片上传配置项 */
|
||||
"scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
|
||||
"scrawlFieldName": "upfile", /* 提交的图片表单名称 */
|
||||
"scrawlPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
||||
"scrawlMaxSize": 20480000, /* 上传大小限制,单位B */
|
||||
"scrawlUrlPrefix": "", /* 图片访问路径前缀 */
|
||||
"scrawlInsertAlign": "none",
|
||||
|
||||
/* 截图工具上传 */
|
||||
"snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
|
||||
"snapscreenPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
||||
"snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
|
||||
"snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
|
||||
|
||||
/* 抓取远程图片配置 */
|
||||
"catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
|
||||
"catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
|
||||
"catcherFieldName": "source", /* 提交的图片列表表单名称 */
|
||||
"catcherPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
||||
"catcherUrlPrefix": "", /* 图片访问路径前缀 */
|
||||
"catcherMaxSize": 20480000, /* 上传大小限制,单位B */
|
||||
"catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
|
||||
|
||||
/* 上传视频配置 */
|
||||
"videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
|
||||
"videoFieldName": "upfile", /* 提交的视频表单名称 */
|
||||
"videoPathFormat": "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
||||
"videoUrlPrefix": "", /* 视频访问路径前缀 */
|
||||
"videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
|
||||
"videoAllowFiles": [
|
||||
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
|
||||
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
|
||||
|
||||
/* 上传文件配置 */
|
||||
"fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
|
||||
"fileFieldName": "upfile", /* 提交的文件表单名称 */
|
||||
"filePathFormat": "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
||||
"fileUrlPrefix": "", /* 文件访问路径前缀 */
|
||||
"fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
|
||||
"fileAllowFiles": [
|
||||
".png", ".jpg", ".jpeg", ".gif", ".bmp",
|
||||
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
|
||||
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
|
||||
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
|
||||
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
|
||||
], /* 上传文件格式显示 */
|
||||
|
||||
/* 列出指定目录下的图片 */
|
||||
"imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
|
||||
"imageManagerListPath": "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */
|
||||
"imageManagerListSize": 20, /* 每次列出文件数量 */
|
||||
"imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
|
||||
"imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
|
||||
"imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
|
||||
|
||||
/* 列出指定目录下的文件 */
|
||||
"fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
|
||||
"fileManagerListPath": "/ueditor/php/upload/file/", /* 指定要列出文件的目录 */
|
||||
"fileManagerUrlPrefix": "", /* 文件访问路径前缀 */
|
||||
"fileManagerListSize": 20, /* 每次列出文件数量 */
|
||||
"fileManagerAllowFiles": [
|
||||
".png", ".jpg", ".jpeg", ".gif", ".bmp",
|
||||
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
|
||||
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
|
||||
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
|
||||
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
|
||||
] /* 列出的文件类型 */
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user