未解之谜
百度搜索算法规范详解https://zy.baidu.com/act/guide?isResponsible=1
百度搜索优化知识大全https://zy.baidu.com/act/seo?isResponsible=1
阿里云开发者课堂 https://edu.aliyun.com/
spark-md5.js 计算文件md5值 :https://github.com/satazor/js-spark-md5
一个提供用户脚本的网站
https://greasyfork.org/zh-CN
用户脚本管理器:Tampermonkey中文文档
https://www.cnblogs.com/grubber/p/12560522.html
Js上传插件 Plupload
drupal
嵌入式WEB开发
CSRF 漏洞
fopen漏洞
Python
阿里云大学PYTHON学习路线
https://edu.aliyun.com/roadmap/python
ThinkPHP list_to_tree、tree_to_list、list_search
vue.js
C盘可以删除的临时文件,也可以用系统自带的磁盘清理程序清除
C:\Windows\ServiceProfiles\NetworkService\AppData\Local\Temp
C:\Windows\SoftwareDistribution\Download
https://support.microsoft.com/zh-cn/windows?ui=zh-CN&rs=zh-CN&ad=CN
https://support.microsoft.com/zh-cn/windows/%E9%87%8A%E6%94%BE-windows-10-%E4%B8%AD%E7%9A%84%E9%A9%B1%E5%8A%A8%E5%99%A8%E7%A9%BA%E9%97%B4-85529ccb-c365-490d-b548-831022bc9b32
CodeIgniter表单验证类使用示例
$this->load->library('form_validation');
$_validate = array(
array('field'=>'classid', 'label'=>'广告分类', 'rules'=>'required|is_id',),
array('field'=>'title', 'label'=>'广告标题', 'rules'=>'trim|required|max_length[50]',),
array('field'=>'time', 'label'=>'广告有效期', 'rules'=>'trim|required',),
array('field'=>'url', 'label'=>'外链地址', 'rules'=>'trim|max_length[255]|valid_url',),
array('field'=>'img', 'label'=>'广告图片', 'rules'=>'required|max_length[255]',),
);
$this->form_validation->set_rules($_validate);
$this->form_validation->set_rules(
'time',
'广告有效期',
array('regex_match[/^30\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - 20\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/]'),
array('regex_match'=>'广告有效期格式错误')
);
if($this->form_validation->run()==FALSE)return ['code':1, 'msg':$this->form_validation->error_string()];
PHP获取网站SSL证书有效期
function getSSLCertificateExpiry($domain, $port = 443) {
// 创建 SSL 上下文,启用证书捕获
$context = stream_context_create([
'ssl' => [
'capture_peer_cert' => true,
'capture_peer_cert_chain' => true,
'verify_peer' => true, // 强烈建议启用证书验证
'verify_peer_name' => true, // 强烈建议启用域名匹配验证
// 如果在容器或特殊环境中遇到 CA 证书问题,可能需要指定 CA 文件路径
// 'cafile' => '/path/to/cacert.pem',
]
]);
// 建立 SSL 连接
$socket = @stream_socket_client("ssl://{$domain}:{$port}", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
if (!$socket) {
return ['error' => "连接失败: {$errstr} (错误码: {$errno})"];
}
// 获取连接参数,提取证书
$params = stream_context_get_params($socket);
if (!isset($params['options']['ssl']['peer_certificate'])) {
return ['error' => '未收到证书'];
}
$cert = $params['options']['ssl']['peer_certificate'];
$certInfo = openssl_x509_parse($cert);
if (!$certInfo) {
return ['error' => '证书解析失败'];
}
// 提取有效期信息
$validFrom = date('Y-m-d H:i:s', $certInfo['validFrom_time_t']);
$validTo = date('Y-m-d H:i:s', $certInfo['validTo_time_t']);
$isExpired = $certInfo['validTo_time_t'] < time();
return [
'subject' => $certInfo['subject']['CN'] ?? 'N/A',
'issuer' => $certInfo['issuer']['CN'] ?? 'N/A',
'date_of_issue' => $validFrom,
'expires_at' => $validTo,
'expires_timestamp' => $certInfo['validTo_time_t'],
'expired' => $isExpired,
'left_days' => floor(($certInfo['validTo_time_t']-time())/86400),
];
}
$domain = 'www.baidu.com'; // 替换为你要查询的域名
$result = getSSLCertificateExpiry($domain);
if (isset($result['error'])) {
echo "错误: " . $result['error'] . "\n";
} else {
echo "证书信息:\n";
echo " 主题 (CN): " . $result['subject'] . "\n";
echo " 签发者: " . $result['issuer'] . "\n";
echo " 颁发时间: " . $result['date_of_issue'] . "\n";
echo " 到期时间: " . $result['expires_at'] . "\n";
echo " 是否已过期: " . ($result['expired'] ? '是' : '否') . "\n";
echo " 剩余天数: " . $result['left_days'] . "\n";
}输出
证书信息: 主题 (CN): baidu.com 签发者: GlobalSign RSA OV SSL CA 2018 颁发时间: 2025-07-09 07:01:02 到期时间: 2026-08-10 07:01:01 是否已过期: 否 剩余天数: 182
$result = getSSLCertificateExpiry($domain);
获取到的证书所有信息:
Array
(
[name] => /C=CN/ST=beijing/L=beijing/O=Beijing Baidu Netcom Science Technology Co., Ltd/CN=baidu.com
[subject] => Array
(
[C] => CN
[ST] => beijing
[L] => beijing
[O] => Beijing Baidu Netcom Science Technology Co., Ltd
[CN] => baidu.com
)
[hash] => 7476f7c7
[issuer] => Array
(
[C] => BE
[O] => GlobalSign nv-sa
[CN] => GlobalSign RSA OV SSL CA 2018
)
[version] => 2
[serialNumber] => 27025959261604984493724308777
[serialNumberHex] => 5753597B3F311D38E6629529
[validFrom] => 250709070102Z
[validTo] => 260810070101Z
[validFrom_time_t] => 1752044462
[validTo_time_t] => 1786345261
[signatureTypeSN] => RSA-SHA256
[signatureTypeLN] => sha256WithRSAEncryption
[signatureTypeNID] => 668
[purposes] => Array
(
[1] => Array
(
[0] => 1
[1] =>
[2] => sslclient
)
[2] => Array
(
[0] => 1
[1] =>
[2] => sslserver
)
[3] => Array
(
[0] => 1
[1] =>
[2] => nssslserver
)
[4] => Array
(
[0] =>
[1] =>
[2] => smimesign
)
[5] => Array
(
[0] =>
[1] =>
[2] => smimeencrypt
)
[6] => Array
(
[0] =>
[1] =>
[2] => crlsign
)
[7] => Array
(
[0] => 1
[1] => 1
[2] => any
)
[8] => Array
(
[0] => 1
[1] =>
[2] => ocsphelper
)
[9] => Array
(
[0] =>
[1] =>
[2] => timestampsign
)
)
[extensions] => Array
(
[keyUsage] => Digital Signature, Key Encipherment
[basicConstraints] => CA:FALSE
[authorityInfoAccess] => CA Issuers - URI:http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt
OCSP - URI:http://ocsp.globalsign.com/gsrsaovsslca2018
[certificatePolicies] => Policy: 1.3.6.1.4.1.4146.1.20
CPS: https://www.globalsign.com/repository/
Policy: 2.23.140.1.2.2
[crlDistributionPoints] =>
Full Name:
URI:http://crl.globalsign.com/gsrsaovsslca2018.crl
[subjectAltName] => DNS:baidu.com, DNS:baifubao.com, DNS:www.baidu.cn, DNS:www.baidu.com.cn, DNS:mct.y.nuomi.com, DNS:apollo.auto, DNS:dwz.cn, DNS:*.baidu.com, DNS:*.baifubao.com, DNS:*.baidustatic.com, DNS:*.bdstatic.com, DNS:*.bdimg.com, DNS:*.hao123.com, DNS:*.nuomi.com, DNS:*.chuanke.com, DNS:*.trustgo.com, DNS:*.bce.baidu.com, DNS:*.eyun.baidu.com, DNS:*.map.baidu.com, DNS:*.mbd.baidu.com, DNS:*.fanyi.baidu.com, DNS:*.baidubce.com, DNS:*.mipcdn.com, DNS:*.news.baidu.com, DNS:*.baidupcs.com, DNS:*.aipage.com, DNS:*.aipage.cn, DNS:*.bcehost.com, DNS:*.safe.baidu.com, DNS:*.im.baidu.com, DNS:*.baiducontent.com, DNS:*.dlnel.com, DNS:*.dlnel.org, DNS:*.dueros.baidu.com, DNS:*.su.baidu.com, DNS:*.91.com, DNS:*.hao123.baidu.com, DNS:*.apollo.auto, DNS:*.xueshu.baidu.com, DNS:*.bj.baidubce.com, DNS:*.gz.baidubce.com, DNS:*.smartapps.cn, DNS:*.bdtjrcv.com, DNS:*.hao222.com, DNS:*.haokan.com, DNS:*.pae.baidu.com, DNS:*.vd.bdstatic.com, DNS:*.cloud.baidu.com, DNS:click.hm.baidu.com, DNS:log.hm.baidu.com, DNS:cm.pos.baidu.com, DNS:wn.pos.baidu.com, DNS:update.pan.baidu.com
[extendedKeyUsage] => TLS Web Server Authentication, TLS Web Client Authentication
[authorityKeyIdentifier] => keyid:F8:EF:7F:F2:CD:78:67:A8:DE:6F:8F:24:8D:88:F1:87:03:02:B3:EB
[subjectKeyIdentifier] => BA:91:7C:55:A9:8F:1F:B0:02:60:27:BB:D7:D3:03:AF:2D:AB:AD:1D
[ct_precert_scts] => Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : AC:AB:30:70:6C:EB:EC:84:31:F4:13:D2:F4:91:5F:11:
1E:42:24:43:B1:F2:A6:8C:4F:3C:2B:3B:A7:1E:02:C3
Timestamp : Jul 9 07:01:09.629 2025 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:44:02:20:35:DB:47:71:C6:0E:36:D4:9E:87:46:9D:
8D:5C:1D:19:7F:A9:53:C0:1A:8F:16:2D:C2:03:2B:71:
0B:C6:1D:53:02:20:22:0E:91:A8:C5:87:93:93:D6:48:
35:F5:24:7B:F6:F5:FF:3D:56:F3:9D:DB:4C:72:86:2D:
4A:AD:77:45:52:CF
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : CB:38:F7:15:89:7C:84:A1:44:5F:5B:C1:DD:FB:C9:6E:
F2:9A:59:CD:47:0A:69:05:85:B0:CB:14:C3:14:58:E7
Timestamp : Jul 9 07:01:09.640 2025 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:46:02:21:00:BC:C9:FA:F8:1A:19:CB:22:CF:BF:6D:
A3:22:F6:A7:36:7B:C5:35:A1:A5:F7:AD:23:B8:59:2D:
8B:97:09:68:E3:02:21:00:AB:19:F4:52:A5:FB:57:80:
2C:64:F1:A9:5F:EE:77:DA:7C:97:78:37:85:8B:0D:41:
CC:85:80:3C:2E:71:5B:81
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : D7:6D:7D:10:D1:A7:F5:77:C2:C7:E9:5F:D7:00:BF:F9:
82:C9:33:5A:65:E1:D0:B3:01:73:17:C0:C8:C5:69:77
Timestamp : Jul 9 07:01:09.600 2025 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:20:1E:5F:24:19:17:79:DD:66:DA:B1:09:B7:
11:9F:DA:3C:49:A5:21:7B:10:1E:FF:7C:8F:E8:12:0B:
45:FE:38:AA:02:21:00:B7:97:A9:BD:A2:27:A1:08:79:
42:B5:18:DE:4E:76:C1:1D:0D:35:AC:F5:32:3B:05:7C:
9D:8C:4C:87:77:A8:0C
)
)ip地址范围与cidr块互转,判断ip地址是否在给定范围或cidr块中
php版
<?php
class Ip_util{
/**
* 将IP地址范围转换为CIDR块。
*
* @param string $range 格式为 "start_ip-end_ip" 的字符串。
* @return string[] 返回一个包含CIDR格式字符串的数组 (e.g., ["192.168.1.0/24"])。
*/
public static function rangeToCIDR($range) {
list($startIp, $endIp) = explode('-', trim($range));
$start = ip2long($startIp);
$end = ip2long($endIp);
if ($start === false || $end === false || $start > $end) {
throw new InvalidArgumentException("Invalid IP range: $range");
}
$results = [];
while ($start <= $end) {
// 寻找以 $start 为起点的最大网络块
$mask = 32;
for ($i = 1; $i <= 32; $i++) {
$blockSize = 1 << $i;
$maskVal = ~($blockSize - 1);
$blockStart = $start & $maskVal;
// 如果这个块的起始地址小于当前start(说明对齐失败),
// 或者这个块的结束地址超过了范围的结束地址,则不能选择此块
if ($blockStart < $start || ($blockStart + $blockSize - 1) > $end) {
break;
}
// 否则,这个块是有效的,更新掩码
$mask = 32 - $i;
}
$results[] = long2ip($start) . '/' . $mask;
$start += 1 << (32 - $mask);
}
return $results;
}
/**
* 将CIDR块转换为IP地址范围。
*
* @param string $cidr 格式为 "ip_address/prefix_length" 的字符串。
* @return string 返回一个IP范围格式的字符串 (e.g., "192.168.1.0-192.168.1.255")。
*/
public static function cidrToRange($cidr) {
list($ip, $prefixLength) = explode('/', trim($cidr));
$ipNum = ip2long($ip);
if ($ipNum === false || !is_numeric($prefixLength) || $prefixLength < 0 || $prefixLength > 32) {
throw new InvalidArgumentException("Invalid CIDR format: $cidr");
}
$prefixLength = (int)$prefixLength;
$netMask = ~((1 << (32 - $prefixLength)) - 1);
$networkAddress = $ipNum & $netMask;
$hostBits = 32 - $prefixLength;
$totalAddressesInSubnet = pow(2, $hostBits);
$broadcastAddress = $networkAddress + $totalAddressesInSubnet - 1;
$startIp = long2ip($networkAddress);
$endIp = long2ip($broadcastAddress);
return "$startIp-$endIp";
}
/**
* 检查IP是否在CIDR列表中
* @param string $ip
* @param array $cidrList
* @return bool
*/
public static function isInCidrList($ip, $cidrList) {
$ipLong = ip2long($ip);
if ($ipLong === false) {
return false; // 无效IP
}
foreach ($cidrList as $cidr) {
list($networkStr, $prefixLen) = explode('/', trim($cidr));
$prefixLen = (int)$prefixLen;
if (!is_numeric($prefixLen) || $prefixLen < 0 || $prefixLen > 32) {
continue; // 跳过无效CIDR
}
$networkLong = ip2long($networkStr);
if ($networkLong === false) {
continue; // 跳过无效网络地址
}
// 计算网络掩码
$mask = ~((1 << (32 - $prefixLen)) - 1);
// 检查IP和网络地址的网络部分是否相同
if (($ipLong & $mask) === ($networkLong & $mask)) {
return true;
}
}
return false;
}
/**
* 检查IP是否在IP范围列表中
* @param string $ip
* @param array $rangeList
* @return bool
*/
public static function isInRangeList($ip, $rangeList) {
$ipLong = ip2long($ip);
if ($ipLong === false) {
return false; // 无效IP
}
foreach ($rangeList as $range) {
list($startStr, $endStr) = explode('-', trim($range));
$startLong = ip2long($startStr);
$endLong = ip2long($endStr);
if ($startLong === false || $endLong === false) {
continue; // 跳过无效范围
}
// 检查IP是否在范围内
if ($ipLong >= $startLong && $ipLong <= $endLong) {
return true;
}
}
return false;
}
}
// --- 示例用法 ---
$ranges = [
'192.168.1.0-192.168.1.255',
'192.168.2.0-192.168.5.0',
'192.168.2.0-192.168.5.128',
'192.168.2.0-192.168.5.255',
'192.168.0.0-192.168.255.255',
'192.1.127.0-192.5.127.255',
'192.1.127.0-192.5.128.169',
'192.1.127.0-192.5.127.0'
];
$cidrs=[];
foreach ($ranges as $range) {
echo "输入范围: $range\n";
$result = Ip_util::rangeToCIDR($range);
$cidrs=array_merge($cidrs,$result);
echo "输出CIDR(s): [" . implode(', ', array_map(function($c) { return "\"$c\""; }, $result)) . "]\n\n";
echo "逆推:\n";
foreach($result as $row){
echo Ip_util::cidrToRange($row),"\n";
}
echo "\n\n";
}
$targetIp='192.5.128.150';
echo "目标IP: $targetIp\n\n";
echo "检查IP是否在范围列表中:\n";
foreach ($ranges as $range) {
$inRange = Ip_util::isInRangeList($targetIp, [$range]);
echo " - '$range': " . ($inRange ? "是" : "否") . "\n";
}
echo "总体结果 (在任一范围内): " . (Ip_util::isInRangeList($targetIp, $ranges) ? "是" : "否") . "\n\n";
echo "检查IP是否在CIDR列表中:\n";
foreach ($cidrs as $cidr) {
$inCidr = Ip_util::isInCidrList($targetIp, [$cidr]);
echo " - '$cidr': " . ($inCidr ? "是" : "否") . "\n";
}
echo "总体结果 (在任一CIDR中): " . (Ip_util::isInCidrList($targetIp, $cidrs) ? "是" : "否") . "\n";
?>
js版
<script>
/**
* IP范围转CIDR列表
* @param {string} ipRange
* @returns {string[]}
*/
function rangeToCIDR(ipRange) {
const [startIp, endIp]=ipRange.split('-');
const ipToInt = ip => ip.split('.').reduce((acc, x) => (acc << 8) + (+x), 0);
const intToIp = int => [24, 16, 8, 0].map(s => (int >> s) & 0xFF).join('.');
let start = ipToInt(startIp);
const end = ipToInt(endIp);
const results = [];
while (start <= end) {
// 找到start的最低位1的位置
let mask = 32;
for (let i = 1; i <= 32; i++) {
const blockSize = 1 << i;
const maskVal = ~(blockSize - 1);
const blockStart = start & maskVal;
if (blockStart < start || blockStart + blockSize - 1 > end) {
break;
}
mask = 32 - i;
}
results.push(`${intToIp(start)}/${mask}`);
start += 1 << (32 - mask);
}
return results;
}
/**
* CIDR转IP范围
* @param {string} cidr
* @returns {string}
*/
function cidrToRange(cidr) {
const ipToInt = ip => ip.split('.').reduce((acc, octet, i) => acc + (parseInt(octet) << (24 - i * 8)), 0);
const intToIp = int => [24, 16, 8, 0].map(shift => (int >>> shift) & 0xFF).join('.');
const [ip, prefixStr] = cidr.split('/');
const prefix = parseInt(prefixStr, 10);
const mask = ~0 << (32 - prefix);
const ipInt = ipToInt(ip);
const network = ipInt & mask;
return intToIp(network)+'-'+intToIp(network + (1 << (32 - prefix)) - 1);
return {
start: intToIp(network),
end: intToIp(network + (1 << (32 - prefix)) - 1)
};
}
/**
* 检查IP是否在CIDR列表中
* @param {string} ip
* @param {string[]} cidrList
* @returns {boolean}
*/
function isIpInCidrList(ip, cidrList) {
const ipLong = ip.split('.').reduce((acc, x) => (acc << 8) + (+x), 0) >>> 0;
if (isNaN(ipLong)) return false; // 无效IP
for (const cidr of cidrList) {
const [networkStr, prefixLenStr] = cidr.split('/');
const prefixLen = parseInt(prefixLenStr, 10);
if (isNaN(prefixLen) || prefixLen < 0 || prefixLen > 32) {
continue; // 跳过无效CIDR
}
const networkLong = networkStr.split('.').reduce((acc, x) => (acc << 8) + (+x), 0) >>> 0;
if (isNaN(networkLong)) {
continue; // 跳过无效网络地址
}
const mask = ~((1 << (32 - prefixLen)) - 1) >>> 0;
if ((ipLong & mask) === (networkLong & mask)) {
return true;
}
}
return false;
}
/**
* 检查IP是否在IP范围列表中
* @param {string} ip
* @param {string[]} rangeList
* @returns {boolean}
*/
function isIpInRangeList(ip, rangeList) {
const ipLong = ip.split('.').reduce((acc, x) => (acc << 8) + (+x), 0) >>> 0;
if (isNaN(ipLong)) return false; // 无效IP
for (const range of rangeList) {
const [startStr, endStr] = range.split('-');
const startLong = startStr.split('.').reduce((acc, x) => (acc << 8) + (+x), 0) >>> 0;
const endLong = endStr.split('.').reduce((acc, x) => (acc << 8) + (+x), 0) >>> 0;
if (isNaN(startLong) || isNaN(endLong)) {
continue; // 跳过无效范围
}
if (ipLong >= startLong && ipLong <= endLong) {
return true;
}
}
return false;
}
// --- 示例用法 ---
const ranges = [
'192.168.1.0-192.168.1.255',
'192.168.2.0-192.168.5.0',
'192.168.2.0-192.168.5.128',
'192.168.2.0-192.168.5.255',
'192.168.0.0-192.168.255.255',
'192.1.127.0-192.5.127.255',
'192.1.127.0-192.5.128.169',
'192.1.127.0-192.5.127.0'
];
cidrs=[];
ranges.forEach(range => {
console.log(`输入范围: ${range}`);
const result = rangeToCIDR(range);
cidrs=cidrs.concat(result);
console.log(`输出CIDR(s): [${result.map(c => `"${c}"`).join(', ')}]\n`);
console.log("逆推:\n");
for(let index in result){
console.log(cidrToRange(result[index])+"\n");
}
/*
$.each(result,function(index,row){
console.log(cidrToRange(row)+"\n");
});
*/
console.log("\n\n");
});
const targetIp = "192.5.128.150";
console.log(`目标IP: ${targetIp}\n`);
console.log("检查IP是否在范围列表中:");
ranges.forEach(range => {
const inRange = isIpInRangeList(targetIp, [range]);
console.log(` - '${range}': ${inRange ? '是' : '否'}`);
});
console.log(`总体结果 (在任一范围内): ${isIpInRangeList(targetIp, ranges) ? '是' : '否'}\n`);
console.log("检查IP是否在CIDR列表中:");
cidrs.forEach(cidr => {
const inCidr = isIpInCidrList(targetIp, [cidr]);
console.log(` - '${cidr}': ${inCidr ? '是' : '否'}`);
});
console.log(`总体结果 (在任一CIDR中): ${isIpInCidrList(targetIp, cidrs) ? '是' : '否'}`);
</script>
批量获取某目录及子孙目录下的所有图片image、视频video、目录dir、目录树dir_tree
/**
* 批量获取某目录及子孙目录下的所有图片image、视频video、目录dir、目录树dir_tree
* @param array $filter_array 要过滤的目录名称列表
*/
function get_file_list($type, $path, $filter_array=array()){
if(!in_array($type, explode(',','image,video,dir,dir_tree')))return return_data(1,'类型错误:'.$type);
/**
* SELF_FIRST 目录从浅到深返回
* CHILD_FIRST 先处理子节点,目录从深到浅返回
*/
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
$photos = [];
$videos = [];
$dirs = [];
foreach ($iterator as $SplFileInfo){
$skip=false;
foreach($filter_array as $filter){
if(strpos($SplFileInfo->getRealPath(), $filter)!==false){
$skip=true;
break;
}
}
if($skip)continue;
/*
$SplFileInfo 实际是 RecursiveDirectoryIterator 类
参考:https://www.php.net/manual/zh/class.recursivedirectoryiterator.php
常用方法:
getExtension 获取扩展名,如:jpg
getFilename 获取文件名,如:abc.jpg
getPathname 返回创建 SplFileInfo 对象时传入的原始路径字符串(不做任何解析或验证),如:D:\web/pictures\2001\a.jpg
getRealPath 返回文件的规范化的绝对路径,如:D:\web\pictures\2001\a.jpg
getSize
getType
isDir
isFile
isLink 快捷方式,会自动跟随与链接文件
*/
if($SplFileInfo->isDir()){
$dirs[$iterator->getDepth()][] = $SplFileInfo->getRealPath();
}else if($SplFileInfo->isFile()){
$cur_path = dirname($SplFileInfo->getRealPath());
$cur_file = $SplFileInfo->getRealPath();
$cur_size = $SplFileInfo->getSize();
switch(strtolower($SplFileInfo->getExtension())){
case 'jpe':
case 'jpg':
case 'jpeg':
case 'png':
//因生成缩略图时可能出错,所以不展示大图片
if($cur_size < 20*1024*1024){
$photos[$cur_path][] = $cur_file;
}
break;
case 'mp4':
$videos[$cur_path][] = $cur_file;
break;
}
/*
$photos[] = [
'getRealPath' => $SplFileInfo->getRealPath(),
'getPathname' => $SplFileInfo->getPathname(),
'getExtension' => $SplFileInfo->getExtension(),
'getFilename' => $SplFileInfo->getFilename(),
'getSize' => $SplFileInfo->getSize(),
'getType' => $SplFileInfo->getType(),
];
*/
}
}
ksort($dirs);
// 构建树形结构
$dir_tree = [];
foreach ($dirs as $depth => $paths) {
foreach ($paths as $path) {
insertPathIntoTree($dir_tree, $path, $path);
}
}
switch($type){
case 'image':
return return_data(0,'',$photos);
case 'video':
return return_data(0,'',videos);
case 'dir':
return return_data(0,'',dir);
case 'dir_tree':
return return_data(0,'',dir_tree);
}
}
//生成目录树
function insertPathIntoTree(&$tree, $currentPath, $rootPath) {
// 计算相对路径
$relativePath = substr($currentPath, strlen($rootPath));
if (empty($relativePath)) {
$tree[$currentPath] = [];
return;
}
// 分割路径
$parts = explode(DIRECTORY_SEPARATOR, trim($relativePath, DIRECTORY_SEPARATOR));
// 找到父路径
$parentPath = $rootPath;
for ($i = 0; $i < count($parts) - 1; $i++) {
$parentPath .= DIRECTORY_SEPARATOR . $parts[$i];
}
// 如果是根目录下的直接子目录
if ($parentPath === $rootPath) {
$tree[$currentPath] = [];
return;
}
// 在树中找到父路径对应的节点
$current = &$tree;
$pathSoFar = $rootPath;
for ($i = 0; $i < count($parts) - 1; $i++) {
$pathSoFar .= DIRECTORY_SEPARATOR . $parts[$i];
// 查找当前路径在树中的位置
$found = false;
foreach ($current as $key => $value) {
if (strpos($key, $pathSoFar) === 0) {
$current = &$current[$key];
$found = true;
break;
}
}
if (!$found) break;
}
// 在父节点中添加当前路径
$current[$currentPath] = [];
}php获取图片方向、纠正图片方向
/**
* 自动纠正图片方向
* 方向经过旋转的图片,在电脑、手机、浏览器中查看时一般会自动纠正,
* 但是在生成缩略图、使用某些打印控件打印时,可能会出现方向不正确的情况。
*/
function rotateImage($imagePath) {
if (!function_exists('exif_read_data')) {
return false; // EXIF扩展未启用
}
if (!file_exists($imagePath)) {
return false; // 文件不存在
}
$exif = exif_read_data($imagePath);
$orientation=1;
if ($exif && isset($exif['Orientation'])) {
$orientation= (int)$exif['Orientation'];
}
// 读取图片
$size = getimagesize($imagePath);
$width = $size[0];
$height= $size[1];
$mime = $size['mime'];
switch ($mime) {
case 'image/jpeg':
$image = imagecreatefromjpeg($imagePath);
break;
case 'image/png':
$image = imagecreatefrompng($imagePath);
break;
case 'image/gif':
$image = imagecreatefromgif($imagePath);
break;
default:
header('Content-Type: '.$mime);
echo file_get_contents($imagePath);
return false;
}
// 根据方向值进行旋转
switch ($orientation) {
case 2:
// 水平翻转
imageflip($image, IMG_FLIP_HORIZONTAL);
break;
case 3:
// 旋转180°
$image = imagerotate($image, 180, 0);
break;
case 4:
// 垂直翻转
imageflip($image, IMG_FLIP_VERTICAL);
break;
case 5:
// 顺时针90° + 水平翻转
$image = imagerotate($image, -90, 0);
imageflip($image, IMG_FLIP_HORIZONTAL);
break;
case 6:
// 顺时针90°
$image = imagerotate($image, -90, 0);
break;
case 7:
// 逆时针90° + 水平翻转
$image = imagerotate($image, 90, 0);
imageflip($image, IMG_FLIP_HORIZONTAL);
break;
case 8:
// 逆时针90°
$image = imagerotate($image, 90, 0);
break;
}
// 输出图片
switch ($mime) {
case 'image/jpeg':
header('Content-Type: image/jpeg');
imagejpeg($image, null, 90); // 90% 质量
break;
case 'image/png':
header('Content-Type: image/png');
imagepng($image, null, 9); // 9级压缩
break;
case 'image/gif':
header('Content-Type: image/gif');
imagegif($image);
break;
}
imagedestroy($image);
}
/*获取图片方向*/
function getImageOrientation($imagePath) {
if (!function_exists('exif_read_data')) {
return return_data(1, 'EXIF扩展未启用');
}
if (!file_exists($imagePath)) {
return return_data(2, '文件不存在');
}
$exif = @exif_read_data($imagePath);
if($exif===null)return return_data(2,'方向无法读取:'.$imagePath);
$orientation=0;
if ($exif && isset($exif['Orientation'])) {
$orientation= (int)$exif['Orientation'];
}
// 方向值说明:
// 1 = 正常
// 2 = 水平翻转
// 3 = 旋转180°
// 4 = 垂直翻转
// 5 = 顺时针90°+水平翻转
// 6 = 顺时针90°
// 7 = 逆时针90°+水平翻转
// 8 = 逆时针90°
$txt='';
switch ($orientation) {
case 1:
$txt="正常方向 (0°)";
break;
case 2:
$txt="水平翻转";
break;
case 3:
$txt="旋转 180°";
break;
case 4:
$txt="垂直翻转";
break;
case 5:
$txt="顺时针 90° + 水平翻转";
break;
case 6:
$txt="顺时针 90°";
break;
case 7:
$txt="逆时针 90° + 水平翻转";
break;
case 8:
$txt="逆时针 90°";
break;
default:
$txt="未知方向";
break;
}
return return_data(0, $orientation.chr(32).$txt, array('orientation'=>$orientation, 'description'=>$txt));
}
function return_data($code=0,$msg='',$data=array()){
return array('code'=>$code, 'msg'=>$msg, 'data'=>$data);
}
js实现浏览器全屏切换
调用浏览器的 Fullscreen API 来实现点击按钮后让整个页面(或指定元素)进入全屏模式
var btn=document.getElementById('fullscreenBtn');
btn.addEventListener('click', function(){
if (document.fullscreenElement && document.exitFullscreen) {
document.exitFullscreen();
return;
}
// 获取整个文档根元素(通常是 )
const elem = document.documentElement;
// 尝试进入全屏(兼容不同浏览器前缀)
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.mozRequestFullScreen) { /* Firefox */
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) { /* Chrome, Safari, Edge */
elem.webkitRequestFullscreen();
} else if (elem.msRequestFullscreen) { /* IE11 */
elem.msRequestFullscreen();
} else {
alert('您的浏览器不支持全屏功能');
}
});PHP try catch示例
try {
throw new Exception("错误消息", 404);
} catch (Exception $e) {
echo "消息: " . $e->getMessage() . "\n"; // 错误消息
echo "代码: " . $e->getCode() . "\n"; // 404
echo "文件: " . $e->getFile() . "\n"; // 文件路径
echo "行号: " . $e->getLine() . "\n"; // 行号
echo "回溯: " . $e->getTraceAsString(); // 调用栈
}
php判断png/gif/webp是否背景透明
function isPngTransparent($filePath) {
$image = imagecreatefrompng($filePath);
if (!$image) return false;
// 获取图像尺寸
$width = imagesx($image);
$height = imagesy($image);
// 检查alpha通道
if (imagecolortransparent($image) >= 0) {
return true;
}
// 逐像素检查透明度
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
$color = imagecolorat($image, $x, $y);
$alpha = ($color >> 24) & 0xFF;
if ($alpha > 0) {
//imagedestroy($image);
return true;
}
}
}
imagedestroy($image);
return false;
}
function isGifTransparent($filePath) {
$image = imagecreatefromgif($filePath);
if (!$image) return false;
// 获取透明色索引
$transparentIndex = imagecolortransparent($image);
// 如果有透明色索引
if ($transparentIndex >= 0) {
// 获取调色板中的透明色
$transparentColor = imagecolorsforindex($image, $transparentIndex);
if ($transparentColor['alpha'] == 127) {
//imagedestroy($image);
return true;
}
}
imagedestroy($image);
return false;
}
function isWebpTransparent($filePath) {
if (!function_exists('imagecreatefromwebp')) {
throw new Exception('WebP支持未启用');
}
$image = imagecreatefromwebp($filePath);
if (!$image) return false;
$width = imagesx($image);
$height = imagesy($image);
// WebP支持alpha通道,检查方式类似PNG
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
$color = imagecolorat($image, $x, $y);
$alpha = ($color >> 24) & 0xFF;
if ($alpha > 0) {
//imagedestroy($image);
return true;
}
}
}
imagedestroy($image);
return false;
}
安装SSL证书后中创中间件InforSuite_AS获取不到session、只能获取第一个cookie项的解决办法
麒麟V10系统+中创蹭件InforSuite_AS10+php,网站一直正常使用,自从安装SSL证书后,网站后台就经常登录不了,session获取不到,cookie也只能获取到请求并头cookie中的第一项。
解决办法:中创中间件管理后台禁用 HTTP2
步骤:中间件后台 > 配置 > server-config > 网络配置 > 网络监听程序 > HTTP > HTTP/2 启用前的对勾去掉 > 保存 > 重启中间件。
附中创中间件忘记管理密码的解决办法:
XXX/as/domains/domain1/config/admin-keyfile 文件是密码存放文件,如果忘记密码,可以手动修改这个文件,重置密码。
可以直接替换整个 admin-keyfile 文件,重置三个默认用户的密码,也可以只替换某一用户的密码串,重置单用户的密码。
1) 创建新的域,使用 sh asadmin create-domain domain2 命令创建 domain2 域,此时 domain2 域下的 admin-keyfile 文件为默认密码文件,用户密码为初始密码。
2) 用 domain2 域下的/as/domains/domain2/config/admin-keyfile 文件,覆盖掉/as/domains/domain1/config/admin-keyfile 文件,重新启动应用服务器,即可使用默认密码登录,登录后请及时修改默认密码。
3) 替换单用户密码可以使用 domain2 下 admin-keyfile 文件中密码串替换domain1 下admin-keyfile中对应用户的密码串。例如,想用重置 inforsAdmin 用户密码,直接打开 domain2/config/下的 admin-keyfile 文件,复制 inforsAdmin 用户行信息,将/domain1/config/admin-keyfile 里面 inforsAdmin 整行替换掉即可,重新启动中间件,使用默认密码登录,登录后请及时修改默认密码。
以下只替换 admin 用户:
admin;{SSHA256}6ttdtB61vruEeIFeYcezgPxZLKHyZtgZRVdrCAEPvvqv3BVwaTTRkQ==,;asadmin;updateTime=2026-1-8 15:03:52默认用户:admin,默认初始密码:Cvicse@as123
