mirror of
https://gitee.com/tawords/tawords-docs
synced 2025-09-01 23:43:27 +08:00
较大变动
This commit is contained in:
187
docs/manual/清单 ToDo/Bug & 已知问题.md
Normal file
187
docs/manual/清单 ToDo/Bug & 已知问题.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# 需修复Bug
|
||||
|
||||
### 网站查单词刷新采用ajax,校验php的sessionID
|
||||
|
||||
### 数据库 表前缀
|
||||
|
||||
### 密码使用密文传输保存,不使用明文传输
|
||||
前台使用`md5(md5(password) + salt)`处理传回后台,`salt`每个用户唯一
|
||||
后台使用`password_hash`获取前台传回<经过md5处理的密码>的哈希值保存数据库,验证时使用`password_verify`
|
||||
> // `password_hash`得到的数据类似于
|
||||
`string(60) "$2y$10$MWf.96gY7Afy70tQoXXV.uRCoS8BOzAbZH10PCu7WCX4oH5FR85Gy"`
|
||||
// php5.5之后才有`password_hash()`
|
||||
// 【**参考资料**】 PHP 加密:Password Hashing API:https://blog.csdn.net/weixin_34055910/article/details/93947848
|
||||
设计安全的账号系统的正确姿势
|
||||
https://blog.coderzh.com/2016/01/03/security-design/
|
||||
|
||||
```php
|
||||
<?php
|
||||
$str = 'chicken,run!';
|
||||
$pwd1 = password_hash($str, PASSWORD_BCRYPT);
|
||||
|
||||
var_dump($pwd1);
|
||||
var_dump(password_verify('chicken,run!', $pwd1)); // 输出 true
|
||||
var_dump(password_verify('chicken,ran!', $pwd1)); // 输出 false
|
||||
|
||||
// var_dump(password_needs_rehash($pwd1, PASSWORD_BCRYPT, ['cost'=>10])); // 输出 false,因为 password_hash() 在加密时,出来默认 cost 为 10 外,还会指定随机的盐值
|
||||
```
|
||||
|
||||
|
||||
什么叫给密码“加盐”?如何安全的为你的用户密码“加盐”?
|
||||
https://zhuanlan.zhihu.com/p/144392745
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* 随机生成四位字符串的salt
|
||||
* 也可以根据实际情况使用6位或更长的salt
|
||||
*/
|
||||
function generateSalt()
|
||||
{
|
||||
// 使用随机方式生成一个四位字符
|
||||
$chars = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9'));
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$str .= $chars[mt_rand(0, count($chars) - 1)];
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码生成
|
||||
* 使用两层hash,将salt加在第二层
|
||||
* sha1后再加salt然后再md5
|
||||
*/
|
||||
function generateHashPassword($password, $salt)
|
||||
{
|
||||
return md5(sha1($password) . $salt);
|
||||
}
|
||||
|
||||
$pdo = new PDO('mysql:host=localhost;dbname=blog_test;charset=utf8mb4', 'root', '');
|
||||
|
||||
$username = 'ZyBlog1';
|
||||
$password = '123456';
|
||||
|
||||
// 注册
|
||||
function register($username, $password)
|
||||
{
|
||||
global $pdo;
|
||||
|
||||
// 首先判断用户是否已注册
|
||||
$pre = $pdo->prepare("SELECT COUNT(id) FROM zyblog_test_user WHERE username = :username");
|
||||
$pre->bindParam(':username', $username);
|
||||
$pre->execute();
|
||||
$result = $pre->fetchColumn();
|
||||
|
||||
// 如果用户名存在,则无法注册
|
||||
if ($result > 0) {
|
||||
echo '用户名已注册!', PHP_EOL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 生成salt
|
||||
$salt = generateSalt();
|
||||
// 密码进行加盐hash处理
|
||||
$password = generateHashPassword($password, $salt);
|
||||
|
||||
// 插入新用户
|
||||
$pre = $pdo->prepare("insert into zyblog_test_user(username, password, salt) values(?, ?, ?)");
|
||||
|
||||
$pre->bindValue(1, $username);
|
||||
$pre->bindValue(2, $password);
|
||||
$pre->bindValue(3, $salt);
|
||||
|
||||
$pre->execute();
|
||||
|
||||
return $pdo->lastInsertId();
|
||||
}
|
||||
|
||||
$userId = register($username, $password);
|
||||
if ($userId > 0) {
|
||||
echo '注册成功!用户ID为:' . $userId, PHP_EOL;
|
||||
}
|
||||
|
||||
// 注册成功!用户ID为:1
|
||||
|
||||
// 查询数据库中的数据
|
||||
$sth = $pdo->prepare("SELECT * FROM zyblog_test_user");
|
||||
$sth->execute();
|
||||
|
||||
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
|
||||
print_r($result);
|
||||
|
||||
// Array
|
||||
// (
|
||||
// [0] => Array
|
||||
// (
|
||||
// [id] => 1
|
||||
// [username] => ZyBlog1
|
||||
// [password] => bbff8283d0f90625015256b742b0e694
|
||||
// [salt] => xOkb
|
||||
// )
|
||||
|
||||
// )
|
||||
|
||||
// 登录时验证
|
||||
function login($username, $password)
|
||||
{
|
||||
global $pdo;
|
||||
// 先根据用户名查表
|
||||
$pre = $pdo->prepare("SELECT * FROM zyblog_test_user WHERE username = :username");
|
||||
$pre->bindParam(':username', $username);
|
||||
$pre->execute();
|
||||
$result = $pre->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 用户名存在并获得用户信息后
|
||||
if ($result) {
|
||||
// 根据用户表中的salt字段生成hash密码
|
||||
$password = generateHashPassword($password, $result['salt']);
|
||||
|
||||
// 比对hash密码确认登录是否成功
|
||||
if ($password == $result['password']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$isLogin = login($username, $password);
|
||||
if ($isLogin) {
|
||||
echo '登录成功!', PHP_EOL;
|
||||
} else {
|
||||
echo '登录失败,用户名或密码错误!', PHP_EOL;
|
||||
}
|
||||
|
||||
// 登录成功!
|
||||
|
||||
// 测试表
|
||||
/*
|
||||
CREATE TABLE `zyblog_test_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`username` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户名',
|
||||
`password` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码',
|
||||
`salt` char(4) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '盐',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
*/
|
||||
```
|
||||
PHP的password_hash()使用实例
|
||||
https://www.jb51.net/article/48180.htm
|
||||
|
||||
> 虽然通过password_hash()创建的哈希密码更加安全,但是却降低了互操作性。
|
||||
如我们使用md5方式,在php中用标准的MD5加密,很容易通过其他语言来校验,如node.js:
|
||||
代码如下:
|
||||
|
||||
```
|
||||
var hash = crypto.createHash('md5').update("123456").digest('hex');
|
||||
if(hash == "e10adc3949ba59abbe56e057f20f883e") console.log('密码正确');
|
||||
```
|
||||
|
||||
而使用password_hash()加密的哈希值基本只能通过PHP的password_verify来校验。
|
||||
|
||||
|
||||
------------
|
||||
|
||||
|
||||
# 已知问题
|
||||
## 登录页面
|
||||
- firefox电脑端测试时发现手机模拟弹出框关闭后网页无法操作,只能刷新;
|
||||
- Chrome电脑版手机模式下全屏后按Esc键,右下角的按钮不变化的问题。
|
28
docs/manual/清单 ToDo/保证Rest API的安全性.md
Normal file
28
docs/manual/清单 ToDo/保证Rest API的安全性.md
Normal file
@@ -0,0 +1,28 @@
|
||||
如果单纯考虑加解密,或者签名方式来保证请求合法,其实是远远不够的。事实上,一个安全的API平台往往需要多方面一起考虑,保证请求安全合法。
|
||||
|
||||
## 1、是不是实际客户端的请求?
|
||||
|
||||
设计专门的私有请求头:定义独有的Request headers,标明有此请求头的请求合法。
|
||||
请求包含请求时间:定义时间,防止中间拦截篡改,只对指定超时范围内(如10秒)的请求予以响应。
|
||||
请求URI是否合法:此URI是否在API平台注册?防止伪造URI攻击
|
||||
请求是否包含不允许的参数定义:请求此版本的这个URI是否允许某些字段,防止注入工具。
|
||||
部分竞争资源是否包含调用时版本(Etag):部分竞争资源,使用If-Match头提供。如用户资金账户查询API,可以返回此时的账户版本,修改扣款时附加版本号(类似乐观锁设计)。
|
||||
|
||||
|
||||
## 2、API平台是否允许你调用(访问控制)?
|
||||
|
||||
访问控制,主要是授权调用部分。API都对外暴露,但是某些公共API可以直接请求,某些,需要授权请求。本质的目的,都是为了验证发起用户合法,且对用户能标识统计计费。
|
||||
|
||||
以HMac Auth为例,我们简单设计一个签名算法。开发者注册时获取App Key、App Secret,然后申请部分API的访问权限,发起请求时:
|
||||
|
||||
所有请求参数按第一个字符升序排序(先字母后数字),如第一个相同,则看第二个,依次顺延。
|
||||
按请求参数名及参数值相互连接组成一个字符串。param1=value1¶m2=value2...(其中包含App Key参数)
|
||||
将应用密钥分别添加到以上请求参数串的头部和尾部:secret + 请求参数字符串 + secret。
|
||||
对该字符串进行 SHA1 运算,得到一个二进制数组。
|
||||
将该二进制数组转换为十六进制的字符串,该字符串为此次请求的签名。
|
||||
该签名值使用sign系统级参数一起和其它请求参数一起发送给API平台。
|
||||
服务端先验证是不是实际客户端的请求,然后按照App Key查找对应App Secret,执行签名算法,比较签名是否一致。签名一致后查看此App Key对应的用户是否有访问此API的权限,有则放行。
|
||||
|
||||
执行成功后包装返回指定格式的结果,进行统计计费。
|
||||
|
||||
https://www.ituring.com.cn/article/208878
|
23
docs/manual/清单 ToDo/借鉴.md
Normal file
23
docs/manual/清单 ToDo/借鉴.md
Normal file
@@ -0,0 +1,23 @@
|
||||
> 按住Ctrl在新窗口打开
|
||||
|
||||
## MdClub
|
||||
[https://community.mdclub.org/articles/2](https://community.mdclub.org/articles/2)
|
||||
[https://www.mdclub.org/](https://www.mdclub.org/)
|
||||
[https://www.mdclub.org/api/Token/login](https://www.mdclub.org/api/Token/login)
|
||||
[]()
|
||||
|
||||
## Discuz Q!
|
||||
[Discuz! Q REST API文档 https://discuz.com/api-docs/v1/LanguagePack.html](https://discuz.com/api-docs/v1/LanguagePack.html)
|
||||
|
||||
## MrDoc
|
||||
[MrDoc觅道文档 https://zmister.com/mrdoc/](https://zmister.com/mrdoc/)
|
||||
|
||||
----------
|
||||
|
||||
## iconfont-阿里巴巴矢量图标库
|
||||
[iconfont-阿里巴巴矢量图标库 https://www.iconfont.cn/manage/index](https://www.iconfont.cn/manage/index)
|
||||
|
||||
----------
|
||||
|
||||
## Django
|
||||
[快速安装指南¶ https://docs.djangoproject.com/zh-hans/3.1/intro/install/](https://docs.djangoproject.com/zh-hans/3.1/intro/install/)
|
132
docs/manual/清单 ToDo/数据库/MySQL数据库优化 & 设计注意事项(参考).md
Normal file
132
docs/manual/清单 ToDo/数据库/MySQL数据库优化 & 设计注意事项(参考).md
Normal file
@@ -0,0 +1,132 @@
|
||||
参考资料:
|
||||
https://www.cnblogs.com/daxian2012/p/11207510.html
|
||||
|
||||
------------
|
||||
|
||||
# 1.数据库设计和表创建时就要考虑性能
|
||||
### 设计表时要注意:
|
||||
- 表字段避免null值出现,null值很难查询优化且占用额外的索引空间,推荐默认数字0代替null。
|
||||
- 尽量使用INT而非BIGINT,如果非负则加上UNSIGNED(这样数值容量会扩大一倍),当然能使用TINYINT、SMALLINT、MEDIUM_INT更好。
|
||||
- 使用枚举或整数代替字符串类型
|
||||
- 尽量使用TIMESTAMP而非DATETIME
|
||||
- 单表不要有太多字段,建议在20以内
|
||||
- 用整型来存IP
|
||||
|
||||
### 索引
|
||||
- 索引并不是越多越好,要根据查询有针对性的创建,考虑在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描
|
||||
- 应尽量避免在WHERE子句中对字段进行NULL值判断,否则将导致引擎放弃使用索引而进行全表扫描
|
||||
- 值分布很稀少的字段不适合建索引,例如"性别"这种只有两三个值的字段
|
||||
- 字符字段只建前缀索引
|
||||
- 字符字段最好不要做主键
|
||||
- 不用外键,由程序保证约束
|
||||
- 尽量不用UNIQUE,由程序保证约束
|
||||
- 使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引
|
||||
简言之就是使用合适的数据类型,选择合适的索引
|
||||
|
||||
### 选择合适的数据类型
|
||||
(1)使用可存下数据的最小的数据类型,整型 < date,time < char,varchar < blob
|
||||
(2)使用简单的数据类型,整型比字符处理开销更小,因为字符串的比较更复杂。如,int类型存储时间类型,bigint类型转ip函数
|
||||
(3)使用合理的字段属性长度,固定长度的表会更快。使用enum、char而不是varchar
|
||||
(4)尽可能使用not null定义字段
|
||||
(5)尽量少用text,非用不可最好分表
|
||||
|
||||
### 选择合适的索引列
|
||||
(1)查询频繁的列,在where,group by,order by,on从句中出现的列
|
||||
(2)where条件中<,<=,=,>,>=,between,in,以及like 字符串+通配符(%)出现的列
|
||||
(3)长度小的列,索引字段越小越好,因为数据库的存储单位是页,一页中能存下的数据越多越好
|
||||
(4)离散度大(不同的值多)的列,放在联合索引前面。查看离散度,通过统计不同的列值来实现,count越大,离散程度越高:
|
||||
原开发人员已经跑路,该表早已建立,我无法修改,故:该措辞无法执行,放弃!
|
||||
|
||||
# 2.sql的编写需要注意优化
|
||||
- 使用limit对查询结果的记录进行限定
|
||||
- 避免select *,将需要查找的字段列出来
|
||||
- 使用连接(join)来代替子查询
|
||||
- 拆分大的delete或insert语句
|
||||
- 可通过开启慢查询日志来找出较慢的SQL
|
||||
- 不做列运算:SELECT id WHERE age + 1 = 10,任何对列的操作都将导致表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边
|
||||
- sql语句尽可能简单:一条sql只能在一个cpu运算;大语句拆小语句,减少锁时间;一条大sql可以堵死整个库
|
||||
- OR改写成IN:OR的效率是n级别,IN的效率是log(n)级别,in的个数建议控制在200以内
|
||||
- 不用函数和触发器,在应用程序实现
|
||||
- 避免%xxx式查询
|
||||
- 少用JOIN
|
||||
- 使用同类型进行比较,比如用'123'和'123'比,123和123比
|
||||
- 尽量避免在WHERE子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
|
||||
- 对于连续数值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
|
||||
- 列表数据不要拿全表,要使用LIMIT来分页,每页数量也不要太大
|
||||
|
||||
# 引擎
|
||||
目前广泛使用的是MyISAM和InnoDB两种引擎:
|
||||
|
||||
### MyISAM
|
||||
MyISAM引擎是MySQL 5.1及之前版本的默认引擎,它的特点是:
|
||||
|
||||
- 不支持行锁,读取时对需要读到的所有表加锁,写入时则对表加排它锁
|
||||
- 不支持事务
|
||||
- 不支持外键
|
||||
- 不支持崩溃后的安全恢复
|
||||
- 在表有读取查询的同时,支持往表中插入新纪录
|
||||
- 支持BLOB和TEXT的前500个字符索引,支持全文索引
|
||||
- 支持延迟更新索引,极大提升写入性能
|
||||
- 对于不会进行修改的表,支持压缩表,极大减少磁盘空间占用
|
||||
|
||||
### InnoDB
|
||||
InnoDB在MySQL 5.5后成为默认索引,它的特点是:
|
||||
|
||||
- 支持行锁,采用MVCC来支持高并发
|
||||
- 支持事务
|
||||
- 支持外键
|
||||
- 支持崩溃后的安全恢复
|
||||
- 不支持全文索引
|
||||
|
||||
总体来讲,MyISAM适合SELECT密集型的表,而InnoDB适合INSERT和UPDATE密集型的表
|
||||
MyISAM速度可能超快,占用存储空间也小
|
||||
|
||||
# 分区
|
||||
|
||||
MySQL在5.1版引入的分区是一种简单的水平拆分,用户需要在建表的时候加上分区参数,对应用是透明的无需修改代码。
|
||||
|
||||
对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成,实现分区的代码实际上是通过对一组底层表的对象封装,但对SQL层来说是一个完全封装底层的黑盒子。MySQL实现分区的方式也意味着索引也是按照分区的子表定义,没有全局索引。
|
||||
|
||||
用户的SQL语句是需要针对分区表做优化,SQL条件中要带上分区条件的列,从而使查询定位到少量的分区上,否则就会扫描全部分区,可以通过EXPLAIN PARTITIONS来查看某条SQL语句会落在那些分区上,从而进行SQL优化,我测试,查询时不带分区条件的列,也会提高速度,故该措施值得一试。
|
||||
|
||||
分区的好处是:
|
||||
|
||||
- 可以让单表存储更多的数据
|
||||
- 分区表的数据更容易维护,可以通过清楚整个分区批量删除大量数据,也可以增加新的分区来支持新插入的数据。另外,还可以对一个独立分区进行优化、检查、修复等操作
|
||||
- 部分查询能够从查询条件确定只落在少数分区上,速度会很快
|
||||
- 分区表的数据还可以分布在不同的物理设备上,从而高效利用多个硬件设备
|
||||
- 可以使用分区表赖避免某些特殊瓶颈,例如InnoDB单个索引的互斥访问、ext3文件系统的inode锁竞争
|
||||
- 可以备份和恢复单个分区
|
||||
|
||||
分区的限制和缺点:
|
||||
|
||||
- 一个表最多只能有1024个分区
|
||||
- 如果分区字段中有主键或者唯一索引的列,那么所有主键列和唯一索引列都必须包含进来
|
||||
- 分区表无法使用外键约束
|
||||
- NULL值会使分区过滤无效
|
||||
- 所有分区必须使用相同的存储引擎
|
||||
|
||||
分区的类型:
|
||||
|
||||
- RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区
|
||||
- LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择
|
||||
- HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式
|
||||
- KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值
|
||||
|
||||
具体关于mysql分区的概念请自行google或查询官方文档
|
||||
。
|
||||
|
||||
# 分表
|
||||
|
||||
分表就是把一张大表,按照如上过程都优化了,还是查询卡死,那就把这个表分成多张表,把一次查询分成多次查询,然后把结果组合返回给用户。
|
||||
|
||||
分表分为垂直拆分和水平拆分,通常以某个字段做拆分项。比如以id字段拆分为100张表: 表名为 tableName_id%100
|
||||
|
||||
但:分表需要修改源程序代码,会给开发带来大量工作,极大的增加了开发成本,故:只适合在开发初期就考虑到了大量数据存在,做好了分表处理,不适合应用上线了再做修改,成本太高!!!而且选择这个方案,都不如选择我提供的第二第三个方案的成本低!故不建议采用。
|
||||
|
||||
# 分库
|
||||
|
||||
把一个数据库分成多个,建议做个读写分离就行了,真正的做分库也会带来大量的开发成本,得不偿失!不推荐使用。
|
||||
|
||||
|
||||
|
7
docs/manual/清单 ToDo/测试用/延长文件上传时间,测试进度条.md
Normal file
7
docs/manual/清单 ToDo/测试用/延长文件上传时间,测试进度条.md
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
// 下面几行测试用,目的是延长文件上传时间,测试进度条
|
||||
// $a = rand(5, 15);
|
||||
// for ($x=0; $x<=3000000; $x++) {
|
||||
// $a+=rand(rand(5, 15), rand(25, 35));
|
||||
// }
|
42
docs/manual/清单 ToDo/测试用/登录页 浏览器书签快速填充登录.md
Normal file
42
docs/manual/清单 ToDo/测试用/登录页 浏览器书签快速填充登录.md
Normal file
@@ -0,0 +1,42 @@
|
||||
Url如下:
|
||||
|
||||
```
|
||||
javascript:void (function() {
|
||||
function debugmode(){
|
||||
document.getElementById('login_username').value = "111111";
|
||||
document.getElementById('login_password').value = "111111";
|
||||
|
||||
document.getElementById('register_username').value = "666666";
|
||||
document.getElementById('register_nickname').value = "六个六";
|
||||
document.getElementById('register_password').value = "666666";
|
||||
document.getElementById('register_password_confirm').value = "666666";
|
||||
|
||||
|
||||
getCaptchaCode(true);
|
||||
}
|
||||
function getCaptchaCode(isFailRetry){
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: 'api/get-captcha-code-test-only.php',
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
login_captcha.value = register_captcha.value = findpwd_captcha.value = res;
|
||||
login_captcha.focus(); register_captcha.focus(); findpwd_captcha.focus();
|
||||
window.getSelection().empty();
|
||||
},
|
||||
error: function (res) {
|
||||
if(isFailRetry) setTimeout(getCaptchaCode(false), 100);
|
||||
else{
|
||||
login_captcha.value = register_captcha.value = findpwd_captcha.value = "验证码开小差啦,点下验证码再试一次吧";
|
||||
login_captcha.focus(); register_captcha.focus(); findpwd_captcha.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
var vercodeimg_onload = function() { setTimeout(debugmode(), 100) };
|
||||
login_vercodeimg.onload = vercodeimg_onload;
|
||||
register_vercodeimg.onload = vercodeimg_onload;
|
||||
findpwd_vercodeimg.onload = vercodeimg_onload;
|
||||
debugmode();
|
||||
}(document));
|
||||
```
|
14
docs/manual/清单 ToDo/环境选择.md
Normal file
14
docs/manual/清单 ToDo/环境选择.md
Normal file
@@ -0,0 +1,14 @@
|
||||
### Nginx相对于Apache
|
||||
#### Nginx相对于Apache的优点:
|
||||
|
||||
- 轻量级,比apache占用更少的内存及资源;
|
||||
- 抗并发,nginx处理请求是异步非阻塞的,而apache则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
|
||||
- 高度模块化的设计,编写模块相对简单
|
||||
- 社区活跃,各种高性能模块出品迅速
|
||||
|
||||
#### Apache相对于Nginx的优点:
|
||||
|
||||
- rewrite,比nginx强大
|
||||
- 动态页面
|
||||
- 模块多,基本想到的都可以找到
|
||||
- 少bug,nginx的bug相对较多
|
@@ -0,0 +1,10 @@
|
||||
http://jz6.cn/post/23
|
||||
|
||||
# uniqid()
|
||||
`uniqid()` 生成不重复唯一标识
|
||||
```
|
||||
md5(uniqid(md5(microtime(true)),true))
|
||||
```
|
||||
# session_create_id()
|
||||
使用`session_create_id()`函数生成唯一标识符,经过实际测试发现,即使循环调用`session_create_id()`一亿次,都没有出现过重复。
|
||||
`session_create_id()`是php 7.1新增的函数,用来生成session id,低版本无法使用。
|
29
docs/manual/清单 ToDo/随笔记/handlebars (草稿).md
Normal file
29
docs/manual/清单 ToDo/随笔记/handlebars (草稿).md
Normal file
@@ -0,0 +1,29 @@
|
||||
```sql
|
||||
handlebars
|
||||
官网:https://handlebarsjs.com/installation.html
|
||||
可借鉴的(堆糖):https://www.duitang.com/p/atlas/?id=117068767
|
||||
查阅资料:https://www.jianshu.com/p/2ad73da601fc
|
||||
|
||||
|
||||
<script type="text/x-handlebars-template" id="bottom-comment-tmpl">
|
||||
<div class="bottom-comment-content">
|
||||
<span>回复</span>
|
||||
<textarea name="comment" id="operate-comment" cols="80" rows="2" placeholder="说些什么吧..."></textarea>
|
||||
</div>
|
||||
<div class="bottom-comment-button">
|
||||
<div class="bottom-comment-photo">
|
||||
<input id="choose-photo" type="file" accept="image/*" style="display:none"></input>
|
||||
<a href="javascript:;" class="comment-add-photo"><i class="icon-photo"></i>添加图片</a>
|
||||
<div class="comment-photo-wrap">
|
||||
<img src="" alt="">
|
||||
<a href="javascript:;" class="photo-edit">编辑</a>
|
||||
<a href="javascript:;" class="photo-delete">删除</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-comment-submit">
|
||||
<a href="javascript:;" class="comment-cancel">取消</a>
|
||||
<a href="javascript:;" class="comment-submit">发送</a>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
```
|
113
docs/manual/清单 ToDo/随笔记/html map标签.md
Normal file
113
docs/manual/清单 ToDo/随笔记/html map标签.md
Normal file
@@ -0,0 +1,113 @@
|
||||
https://www.w3school.com.cn/html5/tag_map.asp
|
||||
```html
|
||||
<img src="planets.gif" alt="Planets" usemap ="#planetmap" />
|
||||
|
||||
<map name="planetmap">
|
||||
<area shape ="rect" coords ="0,0,110,260" href ="sun.htm" alt="Sun" />
|
||||
<area shape ="circle" coords ="129,161,10" href ="mercur.htm" alt="Mercury" />
|
||||
<area shape ="circle" coords ="180,139,14" href ="venus.htm" alt="Venus" />
|
||||
</map>
|
||||
```
|
||||
|
||||
http://www.divcss5.com/html5/h54844.shtml
|
||||
```html
|
||||
首先让我们来看一下htmlmap标签是什么:
|
||||
|
||||
htmlmap标签:定义一个客户端图像映射。图像映射(image-map)指带有可点击区域的一幅图像。
|
||||
|
||||
定义map:
|
||||
|
||||
<mapid="im_map" name="im_map">
|
||||
|
||||
<areashape="rect" coords="0,0,100,100"href="url.html"/>
|
||||
|
||||
</map>
|
||||
|
||||
map标签定义map,area标签定义可点击的热点,area属性;
|
||||
|
||||
shape:定义热点形状,可选参数rect(矩形)、circle(圆形)、poligon(自定义形状)。
|
||||
|
||||
coords:定义形状路径;
|
||||
|
||||
当shape=rect时,四个数字依次为:起点X、起点Y、终点X、终点Y
|
||||
|
||||
当shape=circle时,三个数字依次为:中心点X、中心点Y、半径
|
||||
|
||||
当shape=poligon时,可定义多个路径点,依次为:起点X、起点Y、路径1X、路径1Y、路径2X、路径2Y......
|
||||
|
||||
href定义点击跳转的地址。
|
||||
|
||||
htmlmap标签必需的属性:
|
||||
|
||||
id:unique_name:为map标签定义唯一的名称。
|
||||
|
||||
htmlmap标签可选的属性:
|
||||
|
||||
name:mapname:为image-map规定的名称。
|
||||
|
||||
map标签在HTML中的结构:
|
||||
|
||||
1、coords的对应坐标不用变,只需在JS里面改变其比例就OK!
|
||||
|
||||
<divclass="map_img">
|
||||
|
||||
<imgclass="mapImg" usemap="mapName"src="isphoto/abc.png"alt=""style="width:450px">
|
||||
|
||||
<mapname="mapName">
|
||||
|
||||
<!--方形区域写法-->
|
||||
|
||||
<!--<areashape="rect"coords="605,250,660,305"target="_blank"href="javascript:alert(1);"alt=""/>-->
|
||||
|
||||
<areashape="circle" coords="633,276,28"target="_blank"href="javascript:alert('汽车图标');"alt=""/>
|
||||
|
||||
</map>
|
||||
|
||||
</div>
|
||||
|
||||
2、如果有多张图片,一张图片对应一个map,class不用变,改变map的name值和对应的usemap值就好。name=usemap他们俩是一对CP哦,不要分开它们,给他们一样的值。
|
||||
|
||||
<divclass="map_img">
|
||||
|
||||
<imgclass="mapImg" usemap="mapName"src="isphoto/abc.png"alt=""style="width:450px">
|
||||
|
||||
<mapname="mapName">
|
||||
|
||||
<areashape="circle" coords="633,276,28"target="_blank"href="javascript:alert('汽车图标');"alt=""/>
|
||||
|
||||
</map>
|
||||
|
||||
<!--一张图片对应一个name和usemap-->
|
||||
|
||||
<imgclass="mapImg" usemap="mapName2"src="isphoto/abc.png"alt=""style="width:450px">
|
||||
|
||||
<mapname="mapName2">
|
||||
|
||||
<areashape="circle" coords="633,276,28"target="_blank"href="javascript:alert('第二张图的汽车图标');"alt=""/>
|
||||
|
||||
</map>
|
||||
|
||||
</div>
|
||||
|
||||
html<map>标签常用在为图像的某区域添加超链接!
|
||||
|
||||
用法如下:
|
||||
|
||||
<imgsrc="planets.gif" alt="无法显示此图像" usemap="#planetmap"/>
|
||||
|
||||
<mapid="planetmap" name="planetmap">
|
||||
|
||||
<areashape="rect" coords="0,0,82,126"href="sun.htm"alt="Sun"/>
|
||||
|
||||
<areashape="circle" coords="90,58,3"href="mercur.htm"alt="Mercury"/>
|
||||
|
||||
<areashape="circle" coords="124,58,8"href="venus.htm"alt="Venus"/>
|
||||
|
||||
</map>
|
||||
|
||||
usemap属性获取<map>标签信息,<area>标签定义一个链接区域,shape属性定义区域形状,coords属性定义链接区域的起点坐标和终点坐标
|
||||
|
||||
注释:area元素永远嵌套在map元素内部。area元素可定义图像映射中的区域。
|
||||
|
||||
注释:<img>中的usemap属性可引用<map>中的id或name属性(取决于浏览器),所以我们应同时向<map>添加id和name属性。
|
||||
```
|
8
docs/manual/清单 ToDo/随笔记/js redirect.php.md
Normal file
8
docs/manual/清单 ToDo/随笔记/js redirect.php.md
Normal file
@@ -0,0 +1,8 @@
|
||||
```php
|
||||
<?php
|
||||
class js{
|
||||
public static function to($url) {
|
||||
echo '<script>location.replace("?page={$url}");</script>';
|
||||
}
|
||||
}
|
||||
```
|
7
docs/manual/清单 ToDo/随笔记/js 强制在新窗口打开链接.md
Normal file
7
docs/manual/清单 ToDo/随笔记/js 强制在新窗口打开链接.md
Normal file
@@ -0,0 +1,7 @@
|
||||
```javascript
|
||||
// 在新窗口中打开链接
|
||||
$('body').on('click', '.markdown-body a', function (e) {
|
||||
e.preventDefault();
|
||||
window.open(this.href, '_blank');
|
||||
});
|
||||
```
|
66
docs/manual/清单 ToDo/随笔记/mysql导入txt文件.md
Normal file
66
docs/manual/清单 ToDo/随笔记/mysql导入txt文件.md
Normal file
@@ -0,0 +1,66 @@
|
||||
https://www.cnblogs.com/madman-fly/p/10742724.html
|
||||
【图片见原文】
|
||||
|
||||
1.首先在命令行启动mysql
|
||||
|
||||
net start mysql
|
||||
|
||||
|
||||

|
||||
|
||||
2.登录MySQL(建议使用非root用户)
|
||||
|
||||
mysql --local-infile=1 -u one -p
|
||||
|
||||
|
||||

|
||||
|
||||
3.创建数据库
|
||||
如 CREATE DATABASE menagerie;
|
||||
|
||||
在使用在这个数据库
|
||||
use menagerie
|
||||
|
||||

|
||||
|
||||
创建表
|
||||
|
||||
如:CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),
|
||||
species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
|
||||
|
||||
创建后可以检查一下
|
||||
|
||||
show tables
|
||||
|
||||

|
||||
|
||||
验证表是否按预期方式创建
|
||||
|
||||
DESCRIBE pet;
|
||||
|
||||

|
||||
|
||||
4.创建好txt文件(最好存放在根目录下方便查找)
|
||||
|
||||
在数据库中导入
|
||||
|
||||
LOAD DATA LOCAL INFILE 'C:\pet.txt' INTO TABLE pet;
|
||||
|
||||
若报错
|
||||
|
||||

|
||||
|
||||
可将其改为绝对路径
|
||||
|
||||
LOAD DATA LOCAL INFILE 'C:\\pet.txt' INTO TABLE pet;
|
||||
|
||||
即可导入成功
|
||||
|
||||

|
||||
|
||||
select * from pet;
|
||||
|
||||
)
|
||||
|
||||
至此完成所有工作。
|
42
docs/manual/清单 ToDo/随笔记/mysql查看执行sql语句的记录日志.md
Normal file
42
docs/manual/清单 ToDo/随笔记/mysql查看执行sql语句的记录日志.md
Normal file
@@ -0,0 +1,42 @@
|
||||
https://www.cnblogs.com/jhin-wxy/p/8965888.html
|
||||
|
||||
### 1、使用processlist,但是有个弊端,就是只能查看正在执行的sql语句,对应历史记录,查看不到。好处是不用设置,不会保存。
|
||||
```sql
|
||||
use information_schema;
|
||||
show processlist;
|
||||
```
|
||||
或者:
|
||||
```sql
|
||||
select * from information_schema.`PROCESSLIST` where info is not null;
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
### 2、开启日志模式
|
||||
> 需要root权限
|
||||
#### 1、设置
|
||||
|
||||
```sql
|
||||
-- 日志开启
|
||||
SET GLOBAL log_output = 'TABLE'; SET GLOBAL general_log = 'ON';
|
||||
|
||||
-- 日志关闭
|
||||
SET GLOBAL log_output = 'TABLE'; SET GLOBAL general_log = 'OFF';
|
||||
```
|
||||
|
||||
#### 2、查询
|
||||
|
||||
```sql
|
||||
SELECT * from mysql.general_log ORDER BY event_time DESC;
|
||||
```
|
||||
|
||||
#### 3、清空表(delete对于这个表,不允许使用,只能用truncate)
|
||||
|
||||
```sql
|
||||
-- truncate table mysql.general_log;
|
||||
```
|
||||
|
||||
|
||||
在查询sql语句之后,在对应的`C:\Program Files\MySQL\MySQL Server 5.7\data`文件夹下面有对应的log记录
|
||||
|
||||
ps:在查询到所需要的记录之后,应尽快关闭日志模式,占用磁盘空间比较大
|
27
docs/manual/清单 ToDo/随笔记/php 获取网页URL.md
Normal file
27
docs/manual/清单 ToDo/随笔记/php 获取网页URL.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 代码
|
||||
```php
|
||||
<?php
|
||||
echo dirname($_SERVER['PHP_SELF']).'/index.php?c=admin';
|
||||
echo '<br>';
|
||||
echo dirname('/').'/index.php?c=admin';
|
||||
echo '<br>';
|
||||
$phpSelf = dirname($_SERVER['PHP_SELF']."apple") == "/" ? "" : dirname($_SERVER['PHP_SELF']);
|
||||
echo $phpSelf; exit;
|
||||
exit();
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
# 执行结果
|
||||
|
||||
```
|
||||
/* https://www.only4.work/Admin/新建文件.php */
|
||||
/Admin/index.php?c=admin
|
||||
//index.php?c=admin
|
||||
/Admin
|
||||
|
||||
|
||||
/* https://www.only4.work/新建文件.php */
|
||||
//index.php?c=admin
|
||||
//index.php?c=admin
|
||||
```
|
@@ -0,0 +1,88 @@
|
||||
https://blog.csdn.net/freejs/article/details/84368851
|
||||
|
||||
php学习笔记(二十)mysqli的stmt的预处理类的使用(防止sql注入问题)
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* 处理数据库的扩展库
|
||||
*
|
||||
* mysqli的预处理语句
|
||||
* mysqli_stmt预处理类(推荐使用的类)
|
||||
* 优点:(mysqli和mysqli_result类的相比)
|
||||
* 1.性能:mysqli_stmt高(执行多条类型相同不同数据的sql,不用多次编译sql)
|
||||
* 2.安全上:sql注入问题(用?占位符来解决)
|
||||
* 使用(详情见代码):
|
||||
* ?占位符绑定:(邦定时要注意,后写的信息要与定好的类型匹配否则无法执行)
|
||||
* 例子:$stmt->bind_param("isd",$id,$name,$price);
|
||||
* i:整型
|
||||
* d:double
|
||||
* s:string
|
||||
* b:二进制数
|
||||
* 返回mysqli_stmt预处理类对象:$stmt = $mysqli->prepare($insert)
|
||||
* 一次性将结果全取出来:store_result()
|
||||
*
|
||||
*/
|
||||
|
||||
//使用面向对象的方式:
|
||||
$mysqli = new mysqli("localhost","root","root","hibernate");
|
||||
if (mysqli_connect_errno()){
|
||||
echo "连接失败:".mysqli_connect_error();
|
||||
$mysqli = null;
|
||||
exit();
|
||||
}
|
||||
$mysqli->autocommit(true);
|
||||
$insert = "insert into users values (?,?,?);";
|
||||
//1.返回mysqli_stmt预处理类对象
|
||||
$stmt = $mysqli->stmt_init();
|
||||
//准备一条语句放在服务器上
|
||||
$stmt->prepare($insert);
|
||||
//2.mysqli的方式(简化了操作)
|
||||
//$stmt = $mysqli->prepare($insert);
|
||||
$stmt->bind_param("isd",$id,$name,$price);
|
||||
$id = 32;
|
||||
$name = "ssssss";
|
||||
$price = 21.23;
|
||||
//绑定之后开始执行了
|
||||
if ($stmt->execute()){
|
||||
echo "执行成功";
|
||||
}else {
|
||||
echo "执行失败";
|
||||
}
|
||||
|
||||
|
||||
//2.处理结果集
|
||||
//准备好语句
|
||||
$select = "select * from users where id > ?";
|
||||
//准备一条语句放在服务器上
|
||||
$stmt->prepare($select);
|
||||
$stmt->bind_param("i",$select_id);
|
||||
//绑定结果集(要与查询的字段个数相同)
|
||||
$stmt->bind_result($id,$name,$price);
|
||||
$select_id = 12;
|
||||
//绑定之后开始执行了
|
||||
if ($stmt->execute()){
|
||||
echo "执行成功";
|
||||
}else {
|
||||
echo "执行失败";
|
||||
}
|
||||
//获取结果集(每次获取)
|
||||
while ($stmt->fetch()){
|
||||
echo " <br>$id $name $price";
|
||||
}
|
||||
echo " <br>记录总数:".$stmt->num_rows;
|
||||
|
||||
//一次性将结果全取出来
|
||||
$stmt->store_result();
|
||||
//字段信息
|
||||
$result = $stmt->result_metadata();
|
||||
while ($field = $result->fetch_field()){
|
||||
echo "<br>".$field->name;
|
||||
}
|
||||
|
||||
$stmt->free_result();
|
||||
$stmt->close();
|
||||
$mysqli->close();
|
||||
?>
|
||||
|
||||
```
|
3
docs/manual/清单 ToDo/随笔记/取消内存限制.md
Normal file
3
docs/manual/清单 ToDo/随笔记/取消内存限制.md
Normal file
@@ -0,0 +1,3 @@
|
||||
```
|
||||
ini_set('memory_limit','-1');
|
||||
```
|
7
docs/manual/清单 ToDo/随笔记/可以接入的第三方登录(整理).md
Normal file
7
docs/manual/清单 ToDo/随笔记/可以接入的第三方登录(整理).md
Normal file
@@ -0,0 +1,7 @@
|
||||
QQ
|
||||
微博
|
||||
微信
|
||||
百度
|
||||
脉脉
|
||||
GitHub
|
||||
领英
|
10
docs/manual/清单 ToDo/随笔记/可参考网站.md
Normal file
10
docs/manual/清单 ToDo/随笔记/可参考网站.md
Normal file
@@ -0,0 +1,10 @@
|
||||
天天阅词
|
||||
https://www.tiantianyueci.com/
|
||||
|
||||
抓鸟
|
||||
https://dict.zhuaniao.com/#
|
||||
|
||||
|
||||
翻译:
|
||||
使用条款; 服务条款
|
||||
terms of use
|
666
docs/manual/清单 ToDo/随笔记/文件备份/page_login.css.bak.md
Normal file
666
docs/manual/清单 ToDo/随笔记/文件备份/page_login.css.bak.md
Normal file
@@ -0,0 +1,666 @@
|
||||
/recite-words/static/css/page_login.css.bak
|
||||
|
||||
```css
|
||||
audio,
|
||||
body,
|
||||
caption,
|
||||
div,
|
||||
footer,
|
||||
form,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
header,
|
||||
html,
|
||||
iframe,
|
||||
label,
|
||||
legend,
|
||||
li,
|
||||
main,
|
||||
mark,
|
||||
menu,
|
||||
nav,
|
||||
ol,
|
||||
p,
|
||||
section,
|
||||
span,
|
||||
summary,
|
||||
table,
|
||||
textarea,
|
||||
time,
|
||||
ul,
|
||||
video {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
outline: 0 none;
|
||||
}
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body {
|
||||
margin-bottom: 60px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.mdui-drawer-body-left footer {
|
||||
width: calc(100% - 240px);
|
||||
}
|
||||
main {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 1.7rem 0;
|
||||
}
|
||||
main .login-container,
|
||||
main .register-container {
|
||||
margin-top: 4rem;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
main .upload-container .title {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
main .upload-container .title h1 {
|
||||
font-weight: 300;
|
||||
font-size: 2rem;
|
||||
text-shadow: -5px 5px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
main .upload-container .title p {
|
||||
margin-top: 1rem;
|
||||
font-size: 0.8rem;
|
||||
color: #999;
|
||||
}
|
||||
main .upload-container .success-info {
|
||||
margin-top: 1rem;
|
||||
width: 0;
|
||||
}
|
||||
main .upload-container .success-info .mdui-tab a {
|
||||
text-transform: inherit;
|
||||
}
|
||||
main .upload-container .success-info ul {
|
||||
list-style: none;
|
||||
}
|
||||
main .upload-container .success-info ul li {
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.8rem;
|
||||
border: 1px solid #dadada;
|
||||
background-color: #f7f7f7;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
border-radius: 0;
|
||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
main .upload-container .success-info ul li i.icon-copy {
|
||||
display: none;
|
||||
}
|
||||
main .upload-container .success-info ul li:hover i.icon-copy {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
font-size: 25px;
|
||||
right: 10px;
|
||||
color: #00b0ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
main .console-container .mdui-table td,
|
||||
main .console-container .mdui-table th {
|
||||
padding: 12px 28px;
|
||||
}
|
||||
main .console-container div.item i.mdui-icon {
|
||||
float: left;
|
||||
font-size: 3.7rem;
|
||||
}
|
||||
main .console-container div.item > div {
|
||||
border-radius: 3px;
|
||||
}
|
||||
main .console-container div.item > div p {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
main .system-container .mdui-textfield-label {
|
||||
pointer-events: inherit;
|
||||
}
|
||||
main .system-container .mdui-textfield {
|
||||
overflow: inherit;
|
||||
}
|
||||
main .images-container #info .mdui-dialog-content {
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
main .images-container #info .mdui-btn-group .mdui-btn {
|
||||
margin-left: 0;
|
||||
min-width: inherit;
|
||||
}
|
||||
main .images-container #info img.qrcode {
|
||||
text-align: center;
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
main .images-container #info .mdui-dialog-content {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
main .images-container #info table {
|
||||
width: 100%;
|
||||
}
|
||||
main .images-container #info table tbody tr td[align="right"] {
|
||||
width: 50px;
|
||||
color: #998;
|
||||
}
|
||||
main .images-container .box {
|
||||
min-height: 10rem;
|
||||
}
|
||||
main .images-container .folders-box .item,
|
||||
main .images-container .images-box .item {
|
||||
position: relative;
|
||||
padding: 2rem 0.4rem 0.4rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
transition: all 0.1s;
|
||||
border: 1px solid transparent;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
main .images-container .folders-box .item i.iconfont,
|
||||
main .images-container .images-box .item i.iconfont {
|
||||
display: none;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
font-size: 19px;
|
||||
}
|
||||
main .images-container .folders-box .item i.icon-choice,
|
||||
main .images-container .images-box .item i.icon-choice {
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
color: #cecece;
|
||||
}
|
||||
main .images-container .folders-box .item i.icon-choice:hover,
|
||||
main .images-container .images-box .item i.icon-choice:hover {
|
||||
color: #999;
|
||||
}
|
||||
main .images-container .folders-box .item i.icon-info,
|
||||
main .images-container .images-box .item i.icon-info {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
color: #129cff;
|
||||
}
|
||||
main .images-container .folders-box .item:hover,
|
||||
main .images-container .images-box .item:hover {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
main .images-container .folders-box .item.choice,
|
||||
main .images-container .images-box .item.choice {
|
||||
background: rgba(204, 232, 255, 0.5);
|
||||
border: 1px solid rgba(153, 209, 255, 0.57);
|
||||
}
|
||||
main .images-container .folders-box .item.choice i.icon-choice,
|
||||
main .images-container .images-box .item.choice i.icon-choice {
|
||||
display: block;
|
||||
color: #3b8cff;
|
||||
}
|
||||
main .images-container .folders-box .item:hover i.icon-choice,
|
||||
main .images-container .images-box .item:hover i.icon-choice,
|
||||
main .images-container .folders-box .item.choice i.icon-choice,
|
||||
main .images-container .images-box .item.choice i.icon-choice,
|
||||
main .images-container .folders-box .item:hover i.icon-info,
|
||||
main .images-container .images-box .item:hover i.icon-info,
|
||||
main .images-container .folders-box .item.choice i.icon-info,
|
||||
main .images-container .images-box .item.choice i.icon-info {
|
||||
display: block;
|
||||
}
|
||||
main .images-container .folders-box .item .info,
|
||||
main .images-container .images-box .item .info {
|
||||
cursor: pointer;
|
||||
height: 90px;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
main .images-container .folders-box .item .info img,
|
||||
main .images-container .images-box .item .info img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
main .images-container .folders-box .item .info.image img,
|
||||
main .images-container .images-box .item .info.image img {
|
||||
-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
main .images-container .folders-box .item p.name,
|
||||
main .images-container .images-box .item p.name {
|
||||
color: #555;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
font-size: 12px;
|
||||
margin: 0.3rem auto;
|
||||
line-height: 1.5em;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
main .mdui-textfield .captcha {
|
||||
position: absolute;
|
||||
top: 34px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 140px;
|
||||
cursor: pointer;
|
||||
}
|
||||
main ul.breadcrumb {
|
||||
display: block;
|
||||
flex-wrap: wrap;
|
||||
padding: 0.65rem 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
list-style: none;
|
||||
background-color: #e9ecef;
|
||||
border-radius: 0.2rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
main ul.breadcrumb li {
|
||||
display: inline-block;
|
||||
}
|
||||
main ul.breadcrumb li + li {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
main ul.breadcrumb li + li:before {
|
||||
display: inline-block;
|
||||
padding-right: 0.2rem;
|
||||
color: #6c757d;
|
||||
content: "/";
|
||||
}
|
||||
main ul.breadcrumb li a {
|
||||
cursor: pointer;
|
||||
}
|
||||
main ul.breadcrumb li.active a {
|
||||
cursor: default;
|
||||
color: #6c757d;
|
||||
}
|
||||
main .mdui-table td,
|
||||
main .mdui-table th {
|
||||
padding: 0 10px;
|
||||
}
|
||||
main .mask {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
background: rgba(255, 255, 255, 0.47058824);
|
||||
z-index: 99;
|
||||
}
|
||||
main .mask .content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 100;
|
||||
}
|
||||
.krajee-default .file-footer-caption {
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.krajee-default .file-thumb-progress .progress,
|
||||
.krajee-default .file-thumb-progress .progress-bar {
|
||||
height: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.file-input {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.file-input .file-preview {
|
||||
border: none;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.13);
|
||||
}
|
||||
.file-input .file-preview .fileinput-remove {
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
}
|
||||
.file-input .file-preview .file-drop-zone-title {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.file-input .file-preview .file-preview-thumbnails .krajee-default.file-preview-frame {
|
||||
border: 2px solid transparent;
|
||||
transition: all 0.3s;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.13);
|
||||
}
|
||||
.file-input .file-preview .file-preview-thumbnails .krajee-default.file-preview-frame.hover {
|
||||
border: 2px solid red;
|
||||
}
|
||||
.file-input .file-preview .kv-fileinput-error ul {
|
||||
list-style: none;
|
||||
}
|
||||
.file-input .file-caption-main .form-control {
|
||||
box-shadow: 0 2px 15px 0 rgba(0, 0, 0, 0.13);
|
||||
border: none;
|
||||
height: 40px;
|
||||
padding: 8px 18px;
|
||||
}
|
||||
.file-input .file-caption-main .form-control:focus {
|
||||
z-index: 0;
|
||||
}
|
||||
.file-input .file-caption-main .btn {
|
||||
padding: 8px 18px;
|
||||
border: 0;
|
||||
}
|
||||
.file-input .file-caption-main .btn:first-child {
|
||||
border-left: 1px solid #e2e2e2;
|
||||
}
|
||||
.file-input .file-caption-main .btn:last-child {
|
||||
margin-right: -1px;
|
||||
}
|
||||
.file-input .file-caption-main .btn-file {
|
||||
border-color: #2383eb;
|
||||
background-color: #2383eb;
|
||||
}
|
||||
.file-input .file-caption-main .input-group-append {
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.13);
|
||||
}
|
||||
.file-input .file-caption-main .input-group-append .btn {
|
||||
box-shadow: 0 2px 15px 0 rgba(0, 0, 0, 0.13);
|
||||
}
|
||||
.file-input .file-caption-main .file-caption .file-caption-name {
|
||||
font-size: 90%;
|
||||
}
|
||||
.file-zoom-fullscreen.modal {
|
||||
z-index: 999999;
|
||||
}
|
||||
.mdui-tab-scrollable {
|
||||
padding-left: 0;
|
||||
}
|
||||
.mdui-table-fluid {
|
||||
box-shadow: 0 0 10px 0 rgba(45, 45, 45, 0.13);
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
.mdui-btn-raised {
|
||||
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
.panel {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.13);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.panel .panel-header {
|
||||
padding: 1rem;
|
||||
}
|
||||
.panel .panel-body {
|
||||
border-top: 1px solid #f1f1f1;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
padding: 1rem;
|
||||
}
|
||||
.panel .panel-body-box {
|
||||
border-top: 1px solid #f1f1f1;
|
||||
padding: 1rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
border-bottom-right-radius: 0.5rem;
|
||||
}
|
||||
.panel .panel-footer {
|
||||
padding: 1rem;
|
||||
}
|
||||
.error-box {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
.none {
|
||||
display: none;
|
||||
}
|
||||
#loading-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: none;
|
||||
}
|
||||
#loading-container .mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
}
|
||||
#loading-container .loading {
|
||||
position: absolute;
|
||||
top: 5rem;
|
||||
right: 1rem;
|
||||
z-index: 10000;
|
||||
}
|
||||
.panel-box {
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.13);
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
#menu .quota-container {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 2rem;
|
||||
text-align: left;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
#menu .quota-container progress {
|
||||
background-color: #f6f6f6;
|
||||
display: inline;
|
||||
height: 0.5rem;
|
||||
}
|
||||
#menu .quota-container progress::-webkit-progress-bar {
|
||||
background-color: #e0eaf0;
|
||||
}
|
||||
#menu .quota-container progress::-webkit-progress-value {
|
||||
background-color: #1abc9c;
|
||||
}
|
||||
#menu .quota-container progress::-moz-progress-bar {
|
||||
background-color: #e0eaf0;
|
||||
}
|
||||
#menu .quota-container progress::-moz-progress-value {
|
||||
background-color: #708d9b;
|
||||
}
|
||||
#fab-buttons.mdui-fab-wrapper {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
#search-form .search-input {
|
||||
display: inline-block;
|
||||
padding-bottom: 0.6rem;
|
||||
width: 140px;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
color: #999;
|
||||
text-align: left;
|
||||
background-color: #f5f5f5;
|
||||
z-index: -1;
|
||||
}
|
||||
.pagination {
|
||||
display: inline-block;
|
||||
padding-left: 0;
|
||||
margin: 20px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.pagination > li {
|
||||
display: inline;
|
||||
}
|
||||
.pagination > li > a,
|
||||
.pagination > li > span {
|
||||
position: relative;
|
||||
float: left;
|
||||
text-decoration: none;
|
||||
color: #00b5ad;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ddd;
|
||||
margin-left: -1px;
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.pagination > li:first-child > a,
|
||||
.pagination > li:first-child > span {
|
||||
margin-left: 0;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
.pagination > li:last-child > a,
|
||||
.pagination > li:last-child > span {
|
||||
border-bottom-right-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
.pagination > li > a:hover,
|
||||
.pagination > li > a:focus,
|
||||
.pagination > li > span:hover,
|
||||
.pagination > li > span:focus {
|
||||
z-index: 2;
|
||||
color: #22ddde;
|
||||
background-color: #eeeeee;
|
||||
border-color: #ddd;
|
||||
}
|
||||
.pagination > .active > a,
|
||||
.pagination > .active > a:hover,
|
||||
.pagination > .active > a:focus,
|
||||
.pagination > .active > span,
|
||||
.pagination > .active > span:hover,
|
||||
.pagination > .active > span:focus {
|
||||
z-index: 3;
|
||||
color: #e4e4e4;
|
||||
background-color: transparent;
|
||||
border-color: #e4e4e4;
|
||||
cursor: default;
|
||||
}
|
||||
.pagination > .disabled > span,
|
||||
.pagination > .disabled > span:hover,
|
||||
.pagination > .disabled > span:focus,
|
||||
.pagination > .disabled > a,
|
||||
.pagination > .disabled > a:hover,
|
||||
.pagination > .disabled > a:focus {
|
||||
color: #777777;
|
||||
background-color: #fff;
|
||||
border-color: #ddd;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
body.mdui-theme-layout-dark .markdown-body {
|
||||
color: #eaeaea;
|
||||
}
|
||||
body.mdui-theme-layout-dark .markdown-body a {
|
||||
color: #64adff;
|
||||
}
|
||||
body.mdui-theme-layout-dark .markdown-body img {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
body.mdui-theme-layout-dark .markdown-body .highlight pre,
|
||||
body.mdui-theme-layout-dark .markdown-body pre {
|
||||
background-color: #585858;
|
||||
}
|
||||
body.mdui-theme-layout-dark .markdown-body table tr {
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
body.mdui-theme-layout-dark .markdown-body table tr:nth-child(2n) {
|
||||
background-color: #5d5d5d;
|
||||
}
|
||||
body.mdui-theme-layout-dark .pagination > .disabled > span,
|
||||
body.mdui-theme-layout-dark .pagination > .disabled > span:hover,
|
||||
body.mdui-theme-layout-dark .pagination > .disabled > span:focus,
|
||||
body.mdui-theme-layout-dark .pagination > .disabled > a,
|
||||
body.mdui-theme-layout-dark .pagination > .disabled > a:hover,
|
||||
body.mdui-theme-layout-dark .pagination > .disabled > a:focus,
|
||||
body.mdui-theme-layout-dark .pagination > li > a,
|
||||
body.mdui-theme-layout-dark .pagination > li > span {
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
body.mdui-theme-layout-dark .mdui-btn,
|
||||
body.mdui-theme-layout-dark .mdui-theme-accent-indigo .mdui-dialog-actions .mdui-btn {
|
||||
color: white !important;
|
||||
}
|
||||
body.mdui-theme-layout-dark main .mask {
|
||||
background-color: rgba(47, 45, 45, 0.47058824);
|
||||
}
|
||||
body.mdui-theme-layout-dark main .mask .content .mdui-color-white {
|
||||
color: white !important;
|
||||
background-color: rgba(76, 76, 76, 0.78) !important;
|
||||
}
|
||||
body.mdui-theme-layout-dark main .images-container .folders-box .item p.name,
|
||||
body.mdui-theme-layout-dark main .images-container .images-box .item p.name {
|
||||
color: #a0a0a0;
|
||||
}
|
||||
body.mdui-theme-layout-dark main .images-container .folders-box .item:hover,
|
||||
body.mdui-theme-layout-dark main .images-container .images-box .item:hover {
|
||||
background-color: #212121;
|
||||
}
|
||||
body.mdui-theme-layout-dark main ul.breadcrumb {
|
||||
background-color: #3e3e3e;
|
||||
}
|
||||
body.mdui-theme-layout-dark main ul.breadcrumb li.active a {
|
||||
color: #c3c3c3;
|
||||
}
|
||||
body.mdui-theme-layout-dark main .upload-container .success-info ul li {
|
||||
border: 1px solid #888888;
|
||||
background-color: #303030;
|
||||
color: #d4d4d4;
|
||||
}
|
||||
body.mdui-theme-layout-dark footer {
|
||||
background-color: #303030;
|
||||
}
|
||||
body.mdui-theme-layout-dark .modal-content {
|
||||
background-color: #333;
|
||||
}
|
||||
body.mdui-theme-layout-dark .file-input .file-preview {
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
body.mdui-theme-layout-dark .file-input .file-caption-main .btn:first-child {
|
||||
border-left: 0;
|
||||
}
|
||||
body.mdui-theme-layout-dark .file-input .file-caption-main .form-control {
|
||||
color: #bababa;
|
||||
background-color: #303030;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
body.mdui-theme-layout-dark .file-input .file-caption-main .form-control .file-caption-name {
|
||||
color: #c1c1c1;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
margin-bottom: 120px;
|
||||
}
|
||||
.krajee-default.file-preview-frame {
|
||||
width: 95%;
|
||||
}
|
||||
.krajee-default.file-preview-frame .kv-file-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#loading-container .loading {
|
||||
top: 4.5rem;
|
||||
}
|
||||
main .images-container #info img.qrcode {
|
||||
width: 150px;
|
||||
}
|
||||
footer {
|
||||
height: auto;
|
||||
width: 100% !important;
|
||||
line-height: 1.666;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
}
|
||||
```
|
67
docs/manual/清单 ToDo/随笔记/绘制随机不规则三角彩条.md
Normal file
67
docs/manual/清单 ToDo/随笔记/绘制随机不规则三角彩条.md
Normal file
@@ -0,0 +1,67 @@
|
||||
https://zhuanlan.zhihu.com/p/28257724
|
||||
https://cloud.tencent.com/developer/article/1619012
|
||||
|
||||
|
||||

|
||||
|
||||
```html
|
||||
<style>
|
||||
canvas {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<canvas></canvas>
|
||||
<script>
|
||||
document.addEventListener('touchmove', function (e) {
|
||||
e.preventDefault()
|
||||
})
|
||||
var c = document.getElementsByTagName('canvas')[0],
|
||||
x = c.getContext('2d'),
|
||||
pr = window.devicePixelRatio || 1,
|
||||
w = window.innerWidth,
|
||||
h = window.innerHeight,
|
||||
f = 90,
|
||||
q,
|
||||
m = Math,
|
||||
r = 0,
|
||||
u = m.PI*2,
|
||||
v = m.cos,
|
||||
z = m.random
|
||||
c.width = w*pr
|
||||
c.height = h*pr
|
||||
x.scale(pr, pr)
|
||||
x.globalAlpha = 0.6
|
||||
function i(){
|
||||
x.clearRect(0,0,w,h)
|
||||
q=[{x:0,y:h*.7+f},{x:0,y:h*.7-f}]
|
||||
while(q[1].x<w+f) d(q[0], q[1])
|
||||
}
|
||||
function d(i,j){
|
||||
x.beginPath()
|
||||
x.moveTo(i.x, i.y)
|
||||
x.lineTo(j.x, j.y)
|
||||
var k = j.x + (z()*2-0.25)*f,
|
||||
n = y(j.y)
|
||||
x.lineTo(k, n)
|
||||
x.closePath()
|
||||
r-=u/-50
|
||||
x.fillStyle = '#'+(v(r)*127+128<<16 | v(r+u/3)*127+128<<8 | v(r+u/3*2)*127+128).toString(16)
|
||||
x.fill()
|
||||
q[0] = q[1]
|
||||
q[1] = {x:k,y:n}
|
||||
}
|
||||
function y(p){
|
||||
var t = p + (z()*2-1.1)*f
|
||||
return (t>h||t<0) ? y(p) : t
|
||||
}
|
||||
document.onclick = i
|
||||
document.ontouchstart = i
|
||||
i()
|
||||
</script>
|
||||
```
|
45
docs/manual/清单 ToDo/随笔记/被弃用的url.php.md
Normal file
45
docs/manual/清单 ToDo/随笔记/被弃用的url.php.md
Normal file
@@ -0,0 +1,45 @@
|
||||
```php
|
||||
<?php
|
||||
// 禁止本php文件被单独访问
|
||||
if(basename($_SERVER['PHP_SELF']) == basename(__FILE__)) return;
|
||||
|
||||
|
||||
// 该类中函数使用urldecode和urlencode对参数值进行编码、解码
|
||||
class Url{
|
||||
/**
|
||||
* 将字符串参数变为数组
|
||||
* @param $query
|
||||
* @return array
|
||||
*/
|
||||
public static function convertUrlQuery($query)
|
||||
{
|
||||
$queryParts = explode('&', $query);
|
||||
$params = array();
|
||||
foreach ($queryParts as $param) {
|
||||
$item = explode('=', $param);
|
||||
try {
|
||||
$params[$item[0]] = urldecode($item[1]);
|
||||
} catch (Exception $e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数变为字符串
|
||||
* @param $array_query
|
||||
* @return string
|
||||
*/
|
||||
public static function getUrlQuery($array_query)
|
||||
{
|
||||
$tmp = array();
|
||||
foreach($array_query as $k=>$param)
|
||||
{
|
||||
$tmp[] = $k.'='.urlencode($param);
|
||||
}
|
||||
$params = implode('&',$tmp);
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
```
|
36
docs/manual/清单 ToDo/随笔记/让PHP程序永远在后台运行.md
Normal file
36
docs/manual/清单 ToDo/随笔记/让PHP程序永远在后台运行.md
Normal file
@@ -0,0 +1,36 @@
|
||||
让PHP程序永远在后台运行
|
||||
https://www.cnblogs.com/lookphp/p/5276530.html
|
||||
|
||||
PHP里有个函数很有用。这是在最近的开发中才逐渐用到的。
|
||||
int ignore_user_abort ( [bool setting] )
|
||||
这个函数的作用是指示服务器端在远程客户端关闭连接后是否继续执行下面的脚本。
|
||||
|
||||
setting 参数是一个可选参数。如设置为True,则表示如果用户停止脚本运行,仍然不影响脚本的运行(即:脚本将持续执行);如果设置为False,则表示当用户停止运行脚本程序时,脚本程序将停止运行。
|
||||
|
||||
下面这个例子,在用户关闭浏览器后,该脚本仍然后在服务器上继续执行:
|
||||
|
||||
|
||||
```php
|
||||
ignore_user_abort(); // 后台运行
|
||||
set_time_limit(0); // 取消脚本运行时间的超时上限
|
||||
do {
|
||||
sleep(60); // 休眠1分钟
|
||||
}while(true);
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
<?php
|
||||
ignore_user_abort(); // 后台运行
|
||||
set_time_limit(0); // 取消脚本运行时间的超时上限
|
||||
echo 'start.';
|
||||
while(!file_exists('close.txt')){
|
||||
$fp = fopen('test.txt','a+');
|
||||
fwrite($fp,date("Y-m-d H:i:s") . " 成功了!rn");
|
||||
fclose($fp);
|
||||
sleep(10);
|
||||
}
|
||||
echo 'end.';
|
||||
?>
|
||||
```
|
553
docs/manual/清单 ToDo/随笔记/随笔记.md
Normal file
553
docs/manual/清单 ToDo/随笔记/随笔记.md
Normal file
@@ -0,0 +1,553 @@
|
||||
`$a ?? 0` 等同于 `isset($a) ? $a : 0`。
|
||||
`$a ?: 0` 等同于 `$a ? $a : 0`。
|
||||
`empty`:判断一个变量是否为空(`null` `false` `00` `0` `'0'`这类,都会返回`true`)。
|
||||
`isset`:判断一个变量是否设置(值为`false` `00` `0` `'0'`这类,也会返回`true`)。
|
||||
|
||||
```php
|
||||
// session_status()
|
||||
// https://www.php.net/manual/zh/function.session-status.php
|
||||
// 返回值
|
||||
// PHP_SESSION_DISABLED 会话是被禁用的。
|
||||
// PHP_SESSION_NONE 会话是启用的,但不存在当前会话。
|
||||
// PHP_SESSION_ACTIVE 会话是启用的,而且存在当前会话。
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
mysql.php参考
|
||||
```php
|
||||
// 参考文章:https://www.cnblogs.com/liujunhang/p/10926632.html
|
||||
// PHP 官网 关于MySQL的介绍:https://www.php.net/manual/zh/set.mysqlinfo.php
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
mysql
|
||||
```
|
||||
// 常用sql语句总结
|
||||
// 在上面的代码中,我们尝试了通过mysqli对mysql数据进行的增删改查操作,其中较为核心的是,sql语句的使用。
|
||||
// 下面我们来说一下常用的sql语句语法:
|
||||
|
||||
// 创建数据库
|
||||
// create database 数据库名 default character set = 'utf8';
|
||||
// 创建数据表
|
||||
// create table 数据表名 (
|
||||
// -- 下面是表中的一些字段
|
||||
// id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
// firstname VARCHAR(30) NOT NULL,
|
||||
// lastname VARCHAR(30) NOT NULL,
|
||||
// email VARCHAR(50),
|
||||
// reg_date TIMESTAMP
|
||||
// )
|
||||
// 插入数据
|
||||
// insert into table_name (column1, column2, column3,...) values (value1, value2, value3,...)
|
||||
// 读取数据
|
||||
// select column_name(s) from table_name
|
||||
// 如果传入一个*,则表示搜索所有的数据:
|
||||
|
||||
// select * from table_name
|
||||
// 也可以在后面加入指定条件
|
||||
|
||||
// select * from table_name where 条件
|
||||
// 修改
|
||||
// update table_name
|
||||
// set column1=value, column2=value2,...
|
||||
// where some_column=some_value
|
||||
|
||||
// 删除数据
|
||||
// delete from table_name
|
||||
// where some_column = some_value
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
会话相关
|
||||
```php
|
||||
// // 初始化会话。
|
||||
// // 如果要使用会话,别忘了现在就调用:
|
||||
// session_start();
|
||||
|
||||
// // 重置会话中的所有变量
|
||||
// $_SESSION = array();
|
||||
|
||||
// // 如果要清理的更彻底,那么同时删除会话 cookie
|
||||
// // 注意:这样不但销毁了会话中的数据,还同时销毁了会话本身
|
||||
// if (ini_get("session.use_cookies")) {
|
||||
// $params = session_get_cookie_params();
|
||||
// setcookie(session_name(),"", -1,
|
||||
// $params["path"], $params["domain"],
|
||||
// $params["secure"], $params["httponly"]
|
||||
// );
|
||||
// }
|
||||
|
||||
// // 最后,销毁会话
|
||||
// session_destroy();
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
// //开启 Session
|
||||
// session_start();
|
||||
// // 删除所有 Session 变量
|
||||
// $_SESSION = array();
|
||||
// //判断 cookie 中是否保存 Session ID
|
||||
// if(isset($_COOKIE[session_name()])){
|
||||
// setcookie(session_name(),'',time()-3600, '/');
|
||||
// }
|
||||
// //彻底销毁 Session
|
||||
// session_destroy();
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```
|
||||
//SQL join 用于把来自两个或多个表的行结合起来。
|
||||
|
||||
|
||||
/*
|
||||
https://zhidao.baidu.com/question/1835987585872639700.html
|
||||
SQL语句中AS的意思是:别名。
|
||||
|
||||
AS用处:
|
||||
query时
|
||||
|
||||
用来重新指定返回的column名字。
|
||||
|
||||
示例
|
||||
|
||||
一个table有个column叫 id,query是select id from table1
|
||||
|
||||
如果不想叫id,就可重新命名。
|
||||
|
||||
如叫 systemID,可这样写:select id as systemId from table1。
|
||||
|
||||
create table 或 procedure 时
|
||||
|
||||
as 是个关键字。
|
||||
|
||||
示例
|
||||
|
||||
create table test as select * from table1
|
||||
|
||||
这时会create 一个table test,完全copy table table1里的全部数据。
|
||||
|
||||
create procdure name as (is)
|
||||
|
||||
begin
|
||||
|
||||
end;这时as和is可以互换。
|
||||
*/
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
mysql-connect(full).php.bak
|
||||
```php
|
||||
<?php
|
||||
// 参考文章:https://www.cnblogs.com/liujunhang/p/10926632.html
|
||||
// PHP 官网 关于MySQL的介绍:https://www.php.net/manual/zh/set.mysqlinfo.php
|
||||
|
||||
// 当前页:https://only4.work/recite-words/component/mysql-connect.php
|
||||
|
||||
// *************************************************** 通过mysqli 连接数据库 ***************************************************
|
||||
|
||||
// php 连接Mysql
|
||||
// 通过mysqli
|
||||
|
||||
// 采用面向对象的写法来完成数据库的连接
|
||||
// 设置基础数据库信息
|
||||
require_once "../config.php";
|
||||
|
||||
// 创建连接
|
||||
$conn = new mysqli($mysql_server_name, $mysql_username, $mysql_password, $mysql_database);
|
||||
|
||||
// 如果存储数据的时候出现乱码,那么可以使用下面的代码来解决:
|
||||
mysqli_set_charset($conn,'utf8'); // 解决乱码问题
|
||||
|
||||
// 检测连接是否成功
|
||||
if($conn->connect_error){
|
||||
die("连接失败,错误:" . $conn->connect_error ."<br />");
|
||||
}
|
||||
|
||||
// 否则连接成功
|
||||
echo "数据库连接成功!<br />";
|
||||
|
||||
// *************************************************** 通过mysqli 创建数据库 ***************************************************
|
||||
|
||||
// /*
|
||||
// * 通过mysqli 创建数据库 创建连接语句:$conn = new mysqli($mysql_server_name, $mysql_username, $mysql_password);
|
||||
// */
|
||||
// // 设置sql语句
|
||||
// $sql = "create database stu_01 default character set = 'utf8' ";
|
||||
// // 发送sql语句 并且验证是否创建成功
|
||||
// if($conn->query($sql) === TRUE){
|
||||
// echo "数据库创建成功.";
|
||||
// }else {
|
||||
// echo "数据库创建失败 ,错误信息为:" . $conn->error; // 如果失败输出错误信息
|
||||
// }
|
||||
|
||||
// *************************************************** 通过mysqli 创建数据表 ***************************************************
|
||||
|
||||
// // 使用sql 创建数据表
|
||||
// $sql = "create table stu_info(
|
||||
// id int(6) UNSIGNED auto_increment primary key,
|
||||
// firstname varchar(30) not null,
|
||||
// lastname varchar(30) not null,
|
||||
// email varchar(50),
|
||||
// reg_date timestamp
|
||||
// )";
|
||||
|
||||
// if($conn->query($sql) === TRUE){
|
||||
// echo "数据表创建成功。" ."<br />";
|
||||
// }else {
|
||||
// echo "数据表创建失败,错误信息:" . $conn->error ."<br />";
|
||||
// }
|
||||
|
||||
// *************************************************** 通过mysqli 向数据表中插入信息 ***************************************************
|
||||
|
||||
// // 设置插入数据的sql语句
|
||||
// $sql = "insert into stu_info(firstname,lastname,email) values('张三','张小三','zhangsan@qq.com')";
|
||||
|
||||
// // 发送sql 语句
|
||||
// if($conn->query($sql) === TRUE){
|
||||
// echo "新记录添加成功!"."<br />";
|
||||
// }else {
|
||||
// echo "新记录添加失败,错误信息:" . $conn->error ."<br />";
|
||||
// }
|
||||
|
||||
|
||||
// // 下面开始插入多条数据
|
||||
|
||||
// $sql = "insert into stu_info(firstname,lastname,email) values('张三丰','张君宝','sanfeng@qq.com');";
|
||||
// // 使用.= 的形式进行sql语句连接
|
||||
// $sql .= "insert into stu_info(firstname,lastname,email) values('东方不败','东方拜拜','dongfang@qq.com');";
|
||||
|
||||
// // 发送sql
|
||||
// if($conn->multi_query($sql) === TRUE) {
|
||||
// echo "数据添加成功!" . '<br>';
|
||||
// }else{
|
||||
// echo "数据添加失败,错误信息如下: " . $conn->connect_error . '<br>';
|
||||
// }
|
||||
|
||||
// *************************************************** 通过mysqli 读取数据据库中的信息 ***************************************************
|
||||
|
||||
// // 设置sql 语句,查询全部数据
|
||||
// $sql = "select * from stu_info";
|
||||
// // $sql = "select id ,firstname,lastname from stu_info;";
|
||||
// // $sql = "select * from stu_info where id > 3;";
|
||||
|
||||
// // 发送sql语句,获得查询结果
|
||||
// $result = $conn->query($sql);
|
||||
|
||||
// // 如果查询的结果>0表示查询成功,那么就可以将数据输出
|
||||
// // 函数 num_rows() 判断返回的数据。
|
||||
|
||||
// // 如果返回的是多条数据,函数 fetch_assoc() 将结合集放入到关联数组并循环输出。
|
||||
// if(isset($result->num_rows) && $result->num_rows > 0) {
|
||||
// // 输出数据
|
||||
// while($row = $result->fetch_assoc()){
|
||||
// echo "id" . $row['id'] . '- Name:' . $row['firstname'] . " " . $row['lastname'] . '<br>';
|
||||
// }
|
||||
// }else {
|
||||
// echo "暂无数据" . '<br>';
|
||||
// }
|
||||
|
||||
// *************************************************** 通过mysqli 删除数据 ***************************************************
|
||||
|
||||
// // 设置sql
|
||||
// $sql = "delete from stu_info where lastname = '东方拜拜';";
|
||||
|
||||
// // 发送sql
|
||||
// if($conn->query($sql) === TRUE) {
|
||||
// echo "删除成功" . '<br>';
|
||||
// }else {
|
||||
// echo "删除失败,错误信息为:" . $conn->connect_error . '<br>';
|
||||
// }
|
||||
|
||||
// *************************************************** 通过mysqli 删除数据 ***************************************************
|
||||
|
||||
// // 设置sql语句
|
||||
// $sql = "update stu_info set firstname='张小三小三小三小三小三' where id = 4";
|
||||
|
||||
// // 发送sql语句
|
||||
// if($conn->query($sql) === TRUE) {
|
||||
// echo "修改成功" . '<br>';
|
||||
// }else {
|
||||
// echo "修改失败,错误信息:" . $conn->connect_error . '<br>';
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// *************************************************** 清空数据表 ***************************************************
|
||||
|
||||
// $sql = "TRUNCATE `$mysql_database`.`stu_info`";
|
||||
|
||||
// // 发送sql语句,获得查询结果
|
||||
// $result = $conn->query($sql);
|
||||
|
||||
// *************************************************** 关闭数据库连接 ***************************************************
|
||||
|
||||
// 连接之后,还需要将连接关闭
|
||||
$conn->close();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 常用sql语句总结
|
||||
// 在上面的代码中,我们尝试了通过mysqli对mysql数据进行的增删改查操作,其中较为核心的是,sql语句的使用。
|
||||
// 下面我们来说一下常用的sql语句语法:
|
||||
|
||||
// 创建数据库
|
||||
// create database 数据库名 default character set = 'utf8';
|
||||
// 创建数据表
|
||||
// create table 数据表名 (
|
||||
// -- 下面是表中的一些字段
|
||||
// id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
// firstname VARCHAR(30) NOT NULL,
|
||||
// lastname VARCHAR(30) NOT NULL,
|
||||
// email VARCHAR(50),
|
||||
// reg_date TIMESTAMP
|
||||
// )
|
||||
// 插入数据
|
||||
// insert into table_name (column1, column2, column3,...) values (value1, value2, value3,...)
|
||||
// 读取数据
|
||||
// select column_name(s) from table_name
|
||||
// 如果传入一个*,则表示搜索所有的数据:
|
||||
|
||||
// select * from table_name
|
||||
// 也可以在后面加入指定条件
|
||||
|
||||
// select * from table_name where 条件
|
||||
// 修改
|
||||
// update table_name
|
||||
// set column1=value, column2=value2,...
|
||||
// where some_column=some_value
|
||||
|
||||
// 删除数据
|
||||
// delete from table_name
|
||||
// where some_column = some_value
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
csrf document.txt
|
||||
```
|
||||
[https://www.zhihu.com/question/60102253]
|
||||
|
||||
PHP加了Token验证表单防止CSRF后还有必要做其它的防范吗?比如判断REFERER,再加个验证码之类的?有没有这个必要,目前再写一个模板做练习,已经加上了Token验证,准备再加上判断REFERER时突然觉得这样会不会有点多此一举?或则有什么其它更好的方法吗?
|
||||
|
||||
|
||||
目前的代码是这样的,先判断来源,再判断Token
|
||||
|
||||
//判断请求-登陆
|
||||
if($_GET['login']=='action'){
|
||||
//判断REFERER
|
||||
$referer = $_SERVER["HTTP_REFERER"]; //获取前一页面的 URL 地址
|
||||
$url = $_SERVER["HTTP_HOST"]; //获取本页面的主机 URL 地址
|
||||
//echo "来源页面:$referer </br> 本地页面:$url </br>"; //输出结果(测试用)
|
||||
if(preg_match("|$url|", $referer)){
|
||||
//来源通过,判断Token令牌
|
||||
session_start();
|
||||
if($_POST['token'] == $_SESSION['token']){
|
||||
unset($_SESSION['token']);
|
||||
echo "这是一个正常的提交请求";
|
||||
}else{
|
||||
echo "这是一个非法的提交请求";
|
||||
}
|
||||
}else{
|
||||
echo '非法来源的请求';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[https://blog.csdn.net/qq_31752115/article/details/103775475]
|
||||
php如何防止csrf攻击
|
||||
|
||||
CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:
|
||||
|
||||
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。(推荐学习:PHP编程从入门到精通)
|
||||
|
||||
如:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
|
||||
|
||||
防御CSRF攻击:
|
||||
|
||||
目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。
|
||||
|
||||
(1)验证 HTTP Referer 字段
|
||||
|
||||
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。
|
||||
|
||||
这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。
|
||||
|
||||
因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
|
||||
|
||||
(2)在请求地址中添加 token 并验证
|
||||
|
||||
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。
|
||||
|
||||
要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。
|
||||
|
||||
可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
|
||||
|
||||
(3)在 HTTP 头中自定义属性并验证
|
||||
|
||||
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
note____.txt
|
||||
```php
|
||||
<!-- 涟漪动画效果:mdui-ripple -->
|
||||
<!--按钮稍微小一点:mdui-btn-dense-->
|
||||
<!-- font-size: 3.5em; font-size: 3rem; font-size: 36pt; font-size: 48px;-->
|
||||
|
||||
|
||||
查询IP(有道)API
|
||||
https://foundation.youdao.com/ip/ipinfo
|
||||
|
||||
如果有标DJ的是英式音标,标KK的是美式音标。bai
|
||||
比如你查一个词coat,DJ:du[kəut],KK:[kot]。
|
||||
|
||||
|
||||
若页面需默认用 极速 速核,增加标签:<meta name="renderer" content="webkit">
|
||||
若页面需默认用ie兼容内核,增加标签:<meta name="renderer" content="ie-comp">
|
||||
若页面需默认用ie标准内核,增加标签:<meta name="renderer" content="ie-stand">
|
||||
|
||||
|
||||
|
||||
HTML5 Boilerplate 使用相对协议请求 Google CDN 中的 jQuery ,使用方式为:
|
||||
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
|
||||
<script>!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-1.4.2.js"%3E%3C/script%3E'))</script>
|
||||
上面的例子中除了引用 Google CDN 中的文件外,还添加了一个本地 jQuery 链接,以便连接 Google CDN 失败后,使用本地副本。
|
||||
|
||||
|
||||
|
||||
分享到QQ的缩略图显示设置:未确认是否有效?
|
||||
<meta itemprop="name" content="0047ol"/>
|
||||
<meta name="shareimage" itemprop="image" content="logo.png" />
|
||||
<meta name="keywords" content="0047ol" />
|
||||
<meta name="description" itemprop="description" content="0047ol" />
|
||||
|
||||
H5手Q分享通用接口代码片段(https://blog.csdn.net/qq_35432904/article/details/81704321)
|
||||
<meta itemprop="name" content="网页标题">
|
||||
<meta itemprop="description" content="网页描述">
|
||||
<meta itemprop="image" content="缩略图">
|
||||
|
||||
|
||||
|
||||
error_reporting(0);//禁用错误报告
|
||||
error_reporting(E_ALL ^ E_NOTICE);//显示除去 E_NOTICE 之外的所有错误信息
|
||||
error_reporting(E_ALL^E_WARNING^E_NOTICE);//显示除去E_WARNING E_NOTICE 之外的所有错误信息
|
||||
error_reporting(E_ERROR | E_WARNING | E_PARSE);//显示运行时错误,与error_reporting(E_ALL ^ E_NOTICE);效果相同。
|
||||
error_reporting(E_ALL);//显示所有错误
|
||||
|
||||
js:
|
||||
// var flags = [
|
||||
// {flag:'1',info:'清香1'},
|
||||
// {flag:'2',info:'清香2'},
|
||||
// {flag:'3',info:'清香3'},
|
||||
// {flag:'4',info:'清香4'},
|
||||
// {flag:'5',info:'清香5'}];
|
||||
// var arr = '4';
|
||||
// flags.map(e=>{ if(arr == e.flag){ console.log(e.info); alert(e.info);} })
|
||||
|
||||
|
||||
|
||||
HTMl中Meta标签 参考:https://www.cnblogs.com/cxzhome/p/8448463.html
|
||||
|
||||
|
||||
详解HTML5中rel属性的prefetch预加载功能使用:https://www.cnblogs.com/suyuwen1/p/5506397.html
|
||||
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8'); //网页编码
|
||||
|
||||
header('Content-Type: text/plain'); //纯文本格式
|
||||
|
||||
header('Content-Type: image/jpeg'); //JPG、JPEG
|
||||
|
||||
header('Content-Type: application/zip'); // ZIP文件
|
||||
|
||||
header('Content-Type: application/pdf'); // PDF文件
|
||||
|
||||
header('Content-Type: audio/mpeg'); // 音频文件
|
||||
|
||||
header('Content-type: text/css'); //css文件
|
||||
|
||||
header('Content-type: text/javascript'); //js文件
|
||||
|
||||
header('Content-type: application/json'); //json
|
||||
|
||||
header('Content-type: application/pdf'); //pdf
|
||||
|
||||
header('Content-type: text/xml'); //xml
|
||||
|
||||
header('Content-Type: application/x-shockw**e-flash'); //Flash动画
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
------------
|
||||
|
||||
```php
|
||||
|
||||
```
|
Reference in New Issue
Block a user