受到腾讯一道面试题的启发(不确定是否为官方原题,但至少我看到的这个版本在题目的描述上就存在问题)
什么是php的多维数组类型?
A、php的值也是多种数据类型
B、php的值也是数组类型
C、php的索引值有数字和字母
D、以上都是
这里有一段代码,试着 云运算一下?
<?php
$a = ['test'=>["test"],
"b"=>(function (&$a){
unset($a['test']);
$a['c']='aaa';
})($a)];
var_dump($a);
?>
如果你的答案是
//type 1
array(2) {
["b"]=>
NULL
["c"]=>
string(3) 'aaa'
}
//type 2
array(1) {
["c"]=>
string(3) 'aaa'
}
这两个中的一个的话,那可能你要非常小心了。因为这两个是不正确的。
正确答案
array(2) {
["test"]=>
array(1) {
[0]=>
string(4) "test"
}
["b"]=>
NULL
}
如果你没有仔细的考虑或者了解过IIFE亦或者php的语句执行的话,那你可能就会很重要中招了。
我们逐句来读这段代码
$a = ['test'=>
["test"],//生成二维数组,键是test,值是以test为值,0为键的一维数组
"b"=>(function (&$a){ //IIFE,参数为$a的指针
unset($a['test']); //删除$a的test
$a['c']='aaa';//新增键c,值为aaa
})($a)];
var_dump($a);
上面已经把重要语句逐句理清楚了。咋一看没什么问题,仔细一看也没什么问题,但是问题是“答案为什么和我想的不一样”
问题在哪里呢?
IIFE的参数是$a,可是想像一下,在执行这个函数之前,$a真的存在吗?如果不存在,那传递的这个地址(指针)就是空指针,等于新建了一个变量而已。
对,这就是答案。可是为何?
因为这一条语句并没有执行完成,也就是说,其实这里的二维数组还没有赋值给变量 $a,自然在调用这个变量的时候,就是空的了。
所以在二维数组生成的时候,用IIFE是没有办法unset掉的,这就回答了标题里面的问题。
那么,回到这道面试题,我新提出的问题是,“在声明一个二维数组时,二维数组的第一级键的值一定有数组”。这句话,对吗?我不知道是否有人看到这篇文章,但是答案我已经知道了。而且可以告诉你————不对。
一个IIFE所给的反例:
$a = ['test'=>'',
"b"=>(function (){
return ['I am fisher, 2 divs array'];
})()];
var_dump($a);
云运算一下,来碰一碰?
]]>近日,php吧有吧友发布了一个所谓的2019阿里面试题。且不论真假,
里面有一道题很有意思,而且目前还没有看见一个人出来纠正这个问题。
题目如下:
$x = null;
if ('0xFF' == 255) {
$x = (int)'0xFF';
}
//var_dump($x);
问题:$x的值是多少?
他们给了这样一个“公认”的答案: $x=0而不是255。
然后后面一字一句的说得头头是道,差点让人信以为真。可静下心来,再读这段代码,仔细推敲后,发现了“完全不一样”的答案。
令人觉得可笑的是,这道号称令人值得深思的十大问题之一的问题似乎并没有多少人拿到这道题真正的去深思,甚至哪怕是动手运行一下,显然,“拿来主义”并不是一个良好的学习方式。
那么答案到底是什么呢?
答案是,此题条件不足,无解或存在特解。
说人话就是,在不同的php版本下,这段代码有着不同答案。
在php7+环境下,$x 的值为null. 对,这是一个你最不可能相信的答案。
在php5.6-环境下,$x的值为0.
这是一个非常奇怪的答案,不应该会出现这种情况,除非是刻意而为之。
一个很容易想到的关键,应该是'0xFF' == 255
这里出现问题。
字符串与数字进行比较,根据C语言的类型转换运算,低类型应该向高类型进行隐式转换。所以这里字符串要转为int类型。明显根据经验,php会使用is_numeric进行转换,看来,问题的根源就在于此了。
为了证明猜测的正确性,我们可以用以下语句来检验。
$x = null;
if ('0xff' == 255) {
$x = (int)'0xFF';
}
var_dump('0xff'+0);
var_dump(is_numeric('0xff'));
var_dump((int)'0xff');
var_dump('0xff' == 255);
语句 | php7.x | php5.x | 对比 |
---|---|---|---|
'0xff'+0 | int(0) | int(255) | 出现差异 |
is_numeric('0xff') | bool(false) | bool(true) | 出现差异 |
(int)'0xff' | int(0) | int(0) | 正常 |
'0xff' == 255 | bool(false) | bool(true) | 出现差异 |
语句解释:
'0xff'+0
: 强制类型转换且不改变数值,非常常见的一种数值化字符串方法。
is_numeric('0xff')
:判别字符串形式下的十六进制,php5.x与7.x相差较大,见后文说明。
(int)'0xff'
:使用int强制转换,从左到右读取数字,遇到非数字结束。
'0xff' == 255)
:对比结果。
很明显,结果出来了。确实是is_numeric出现了问题。
事实上,官网手册上也验证了我的猜测。
PHP 7.0.0+ Strings in hexadecimal (e.g. 0xf4c3b00c) notation are no longer regarded as numeric strings, i.e. is_numeric() returns FALSE now.
为何要更改对字符串形式的16进制的解析呢?这个问题说来也简单。因为is_numeric并不是一个安全的函数,解析字符串形式的16进制很可能引起sql注入的安全问题,这里不过多讨论,想了解更多的请百度相关文章。所以在php7+,is_numeric不再解析字符串形式的16进制,是为了更加的安全。不论这道题是否是所谓的“2019阿里面试题”,希望所有还在这条路上摸索的人,都要去质疑这种网上流传已久的“神”题。我更加希望这不是阿里的面试题,因为如果HR不加思索的从网上“拿”这个题目出来让这些phper去做,甚至连技术负责人把关都没把到,那可能又是一番笑话了。所以,环境才是最重要的,代码离开了环境,谁能保证永远坚持不懈的动下去。共勉
]]>好久没有写文了,毕竟人是越来越懒的。
之前写过一文,说的是 减少if-else的滥用,提高代码可读性。里面提到了用if-return、表驱动等多种方法来代替if-else,可是具体该怎么用以及改进的方式并不是那些清晰。今天说的这个其实还是一样的,不过在此基础上,又添加了一些内容。
]]>闲暇之时,喜欢在我的ireader上面看点读物,当然,也免不了无聊时看点打发时间的小说。ireader就这点好,看网文方便。尽管号称有50w的书源,但是我关注的一些正经小说在上面也找不到,毕竟独家版权的不在少数。那就只有到处找一些精校后的资源(一般都是完结两三年的,对作者的影响较小。也会看正版啦,只不过自带商城上面没有,也没有办法离线保存),除开一些别人已经精心制作好的,其他一些epub尽管能用,但是内容和排版却不是那么尽人意。自己动手的话,耗时也比较大。有人会问,为什么不用一些转换工具,比如EasyPub、ePUBee Magic等呢?甚至还有在线转换工具ePUBee之类的。是啊,这么多可选择的工具,还要去造轮子。
可是这些工具都有共通之处,那就是会在一些你看不到的地方甚至看得到的地方增加广告。或许是我过于追求完美,无法容忍。所以便花了两个夜晚的时间制作出来这个无广告、无门槛(?)的工具————epubBuilder。这只是一个非常初期的版本,可以在本地使用,稍微改改就能直接上线变成一个互联网工具。岂不美哉?
打开 index.php ,看到如下内容,需要填写的内容都在后面有备注,按实际情况填写即可。填写完成之后用CLI模式,控制台直接输入 php index.php
即可
<?php
define('ROOT', dirname(__FILE__) . '/');
define('TMPDIR', ROOT . 'tmp');
define('OS', TMPDIR . '/OEBPS/');
require ROOT . 'lib/epub.class.php';
## 填写区,勿动以上内容
$config = [
'styles' => '', //自定义样式路径,本地
'txtPath' => ROOT . '此处填写txt文件名称', //把txt文件放到index.php文件目录下
'coverImg' => '', //自定义封面图片路径,可以为网络图片地址,建议放在本地
'toc' => false, //是否要插入正文目录. ireader对正文目录的兼容效果不好(实际上是不支持dl dd标签),默认关闭。
'patternType' => 1, //必填,书籍目录类型,见下方参数说明,
'creater' => '', //作者,必填
'bookName' => '', //书名,必填
'language' => 'zh-CN', //语言,默认中文
'date' => date("Y-m-d"), //发布时间,默认当前日期
];
## 填写区结束,勿动以下内容
(new epub($config))->epub_builder();
1
第xxx章/回/部/节/集/卷 xxxx。标准格式推荐,大作基本符合类型1. 示例: 第1520章 我有男朋友了
2
类型1 + 简介/前言/序章/楔子/终章/后记/尾声/番外。在类型1的基础上扩充了其他常见标题,标题不包括段前空白。示例: 番外 我与男朋有的那段往事
3
同类型2,区别在于类型3包括段前空白,容错率底(匹配更精准,建议选择这个)示例:简介 我叫你老公
4
Chapter/Section 序号 标题。 英文书籍常用此格式,示例: Chapter 1 我来自地球
5
正文 序号。非标准格式,示例:正文 12
6
序号 标题。晋江常用标题,示例: 1 我就是李明亮,阁下?
实现方法比较简单。epub的本质就是zip,所以只需要生成对应的html章节页面,和对应的目录信息之后,然后压缩到一起。html和目录均采用模板文件生成,这样处理之后的所有标准格式。
]]>之前在文章吧务公开后台的实现与功能分析【2017.10.02更新】里面提到过吧务公开后台源码的事情,至今这个源码还在维护着。不过后面倒是由于时间关系,就没有再公开发布了。同时,原来这个代码里面可能还涉及到一些公后台的ID隐私方面的问题,而后几经改版,最终还是决定重新写一个,同时我也将其公开在了github上。不过虽然改版了这么多次,但是还是有一些问题亟需解决,比如验权问题,这样就可以解决很多不必要的麻烦。但是还是来得及去完成,因为确实时间不太充裕,不过就目前来讲,已经比较完善了,后面可能会增加账号和密码(自行设置),这样可以防止机器人爬取、相对公开比较稳妥,在必要的时候告知账号密码,这样便可以由用户自行查询。
贴吧UEG系统日常发疯删帖,吧务整天被骂背锅,说出来大家都不信。眼见为实耳听为虚,我没有亲眼看见怎么知道是不是你在权限我呢?马上吧务换届,权限狗整天只知道水贴不干事,凭什么我要支持?选出来的吧主到底多久没有在线了,到底是哪个吧务一直任劳任怨?一个公开、透明的吧务后台,用事实说话,吧友的眼睛看得见,你的付出都值得,所有的努力都被记录着,最终都会有回报
打开 config.php,其他文件勿动。
$config = [
'bduss' => "你的BDUSS", //此处输入有后台查看权限吧务的BDUSS
'kw' => '吧名', //在吧名处填写需要公开吧务后台的贴吧
'showpic' => true, //boolean值,是否开启图片(需要消耗服务器资源进行转存),根据服务器情况,可关闭
'hideopt' => true, //boolean值,是否隐藏操作人按钮,建议开启(保护操作人隐私)
];
以火狐浏览器为例,打开浏览器进入 https://tieba.baidu.com/ ,按下F12 -> 存储 -> cookie -> BDUSS
其他浏览器类似,不理解可以百度
建议 php >=5.6,部分分类贴吧配置了https,需要修改publicBackstage.class.php里面的cget方法,在curl_setopt($ch, CURLOPT_COOKIE, $cookie)
语句后面填上以下内容:
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
其他问题可以提问
]]>首先,区别 Error 和 Exception 两个概念,这是两个不同的东西。错误是不可忽视的,异常/高级别的错误通常会引起程序停止,而低级别的错误如notice等是可选择忽视的,一般不会造成程序停止运行。当然,个人认为,在不区分语境的情况下,有时出错和出问题可以认为是同一个意思,尽管这两者产生的影响程度上有很大的差别。当我们说到抑错机制的时候,很自然的联想到try-catch接下来说的内容以try-catch的某些方面通过问题的形式展开。
]]>我遇见不少人都是这样,多层逻辑嵌套,看似条例清晰、逻辑关系明了。实际上读起来真的很费力。看个最简单的例子,一吧友A想要发一个帖子宣传xx产品,需要征求所有吧主(bz1,bz2)一致同意后才可以发帖。
有人可能会这样写:
function getPostAgree(){
$agree = false; //flag
if ($bz1 == "agree){
$agree = true;
if ($bz == "agreem){
$agree = true;
}else{
$agree = false;
}
} else {
$agree = false;
}
return $agree;
}
看上去很自然. 逻辑也很清楚,bz1同意了之后bz2再同意肯定就没啥问题了.
有人会这样写:
function getPostAgree(){
$agree == false; //flag
if($bz1 == 'agree' && $bz2 == "agree"){
$agree = true;
}else{
$agree = false;
}
return $agree;
}
这样看上去逻辑更加清楚了,两个吧主同时同意.
还有第三种 第四种:
function getPostAgree(){
$agree == false; //flag
if($bz1 == 'disagree'){
return $agree;
}
if($bz2 == 'disagree'){
return $agree;
}
return $agree=true;
}
function getPostAgree(){
$agree == false; //flag
$bz = [$bz1,$bz2];
if(!in_array('disagree',$bz)){
$agree=true;
}
return $agree;
以上看上去都行得通,那么现在又多个1个吧主呢?10个呢?50个呢?
第一个嵌套50个if - else
第二个写49个&&
第三个写50个if
第四个,变成50的数组。而且,同时可以分离出所有bz
$bz = [$bz1,$bz2];
function getPostAgree()
{
global $bz;
$agree = false; //flag
$agree == !in_array("disagree", $bz);
return $agree;
}
很久很久之前便写过一个云删帖的代码,不过仍然有一定的问题。加上云删帖会降低吧务的勤劳度,所以一直都放在那里没有再管。今天日常逛吧的时候,发现有位吧友希望能用云删帖的方式减少吧务工作量,突然想起我曾经写过一个。不过翻遍硬盘都没有找到,很显然的日常清理又没了。于是花了一两个小时重新写了一个,并调整了一些策略和功能。
其实一直都开源来着,只不过一直没有时间。终于找了时间填了这个大坑,期间也收到过很多朋友的邮件,告知无法运行的问题,忙的没时间去填这些坑。终于 某平台的开发工作告一段落,目前只需要维护插件,所以腾出手来开始琢磨这些。
目前已经将源码放在github上了,本文下面也有更新的链接。可以直接下载部署到你的服务器上。
TiebaCloudDel
以下为配置信息的参数说明,具体请修改$config里面的内容
以CLI模式运行,同时需设置INTERVAL参数。如果不理解,请勿修改。默认false
首次运行后程序 自动监控,无需挂云监控。常驻后台,小内存请用云监控代替
CLI => true;
interval => 60 * ; //2min
具有管理身份的BDUSS,建议语音小编
bduss => ''
需要监控的吧名
kw => '吧名';
使用客户端接口,速度快效率更高,但无法限制发帖用户等级。默认开启,关闭改为false
注意:目前开发版只能使用客户端接口,此开关无效.
wap => (boolean) true;
封禁用户开关,默认不封禁,封禁改为true
block => (boolean) false;
封禁天数,小吧或者有权限的小编请设置为1,否则不会生效。
days => 1;
封禁理由,如果不想留理由直接写为''即可
reason => '违反吧规'
广告检测规则
ad 数组
检测模式: 关键词模式,屏蔽正则。默认开启,使用正则设为 fasle;
str => (boolean) true;
如果是正则模式,在 p键 中填入正则表达式,注意使用//将表达式包围起来。
如果有多个表达式,请用如下形式:
'p' => ['/我.*?开车/',
'/打.*?钱/',
'/\d{5,11}/',
],
如果是关键词模式,请直接填写关键词。多个关键词请用如下形式:
'p' => ['【视频】',
'有小哥哥要恋爱的嘛',
'下面好痒',
],
不要将匹配词设置太多,如果你的服务器不够强大。建议在15个以下
贴吧云删帖V4.0
访问密码:[reply]密码:帅B[/reply]
本文档提取于高校客户端自带帮助文件,并依据实际情况做了一定的调整。部分操作可能需要对电脑有一定了解的童鞋才能流畅的进行,页面中带有相当量的截图以及大量的注释。如果仍有问题,可以在本页面下方附加评论。
错误代码:112 获取拨号模块信息失败,找不到模块信息
错误代码:120 加载升级程序配置信息失败
错误代码:123 升级程序启动失败,请检查用户目录权限
错误代码:130 忘记账号
错误代码:131 忘记密码
错误代码:132 修改密码
错误代码:133 解除手机号码绑定
错误代码:134 程序未正常启动,可能是由于未正常安装或主程序被移动
错误代码:135 加载资源文件失败
错误代码:136 软件运行环境被破坏
错误代码:137 发现代理软件,请确认退出代理软件
错误代码:619 无法连接到指定的服务器,用于此连接的端口已关闭
错误代码:629 连接被远程计算机终止
错误代码:633 调制解调器(或其它连接设备)已在使用,或没有正确配置
错误代码:651 调制解调器(或其他连接设备)报告了一个错误
错误代码:678 远程计算机没有反应
错误代码:691 已拒绝远程连接,因为未识别出你提供的用户名和密码组合
错误代码:711 操作无法完成,因为他无法及时启动远程访问连接管理器服务,请重试此操作
错误代码:718 因为远程计算机不能及时反应,此连接已被终止。
错误代码:720 不能建立到远程计算机的连接,你可能需要更改此连接的网络设置
错误代码:756 已经拨打该连接
错误代码:769 无法连接到指定目标
错误代码:813 建立了前一个宽带连接的情况下,你在使用相同的设备或端口尝试建立一个宽带连接,请断开前一个连接,然后重新建立连接
好久没更新啦.
写了快四周的论文,大家都知道,用word写论文,TA的排版一直不太好.
然而,很多人还是会选择用word,为什么呢?
因为latex写起来真的不是那么容易的.重复的用代码写公式,很是心累.
所以为了让排版更好看,为了让
.
先在word上大致排版,然后转latex精校是有必要的(对我而言确实有必要).
所以,花了一些时间在网上找了一大堆的插件,但是都不是很满意,因为要(nan)收(po)费(jie).
直到我遇到了这个插件
TA让我找到了初恋般的感觉.(好吧我特么又在骗人了!tan90°!!!)
这个插件很棒,因为TA只需要如下环境即可存活.
Microsoft Windows 2000/XP/2003/Vista/7/8
Microsoft Word XP/2003/2007/2010/2013
MathType is needed for converting MathType and Equation Editor equations
相比某只支持word2003来说,已经很感人了.
好了废话不多说.
工作环境:.net
作案工具:dnSpy
简单的运用一下查壳工具什么的查一下壳.
嗯,很棒.一眼就看出来是祖传的.net
图在此
首先我们在word里面随便打开一个文档,点击导航栏 word-to-latex
然后打开about,查看一下注册需要的哪些内容
呃这个...这个,因为我已经注册了.所以这里无法显示未注册内容... 当然是选择原谅我啦!
**没关系,让我这个p图小能手给你p一个,嘿嘿! **
铛铛铛~就是这个啦
随便输入一个邮箱和注册码之后,点击register.
果然提醒我invalid license key.
所以接下来
找到安装目录,再经过我谨慎严密十足的观察10s后,我随机的选择了word-to-latex-lib.DLL.
没错就是因为TA长得很可疑!lib里面一定有交易!
载入dnSpy,这里说明一下我为什么选择dnSpy,嗯,没什么原因.长得好看,受不了,贼喜欢~
在最下方找到载入的word-to-latex-lib.dll,千万别点错了!
搜索
(别问我为什么不搜索
invalid license key,你试试~)
结果里面有
等,接下来就要凭着我们多年的起名经验~让本著名的起名风水大师开坛算一卦~
嗯,
应该是在某一个需要注册或者授权的类里面会用到这个
method,属于结果调用类,而
IsRegistered应该是标记是否为注册用户(trade.py users),如果没有注册,则会提醒pay for py,属于先行判断类.这两者肯定有相互印证的地方.
两个都有可能,那么挨个看吧~
双击进入get_IsRegistered
// Token: 0x1700000F RID: 15
// (get) Token: 0x060000FC RID: 252 RVA: 0x0000BC64 File Offset: 0x0000AC64
public bool IsRegistered
{
get
{
return KeyList.IsNoCheck(this.serialKey) || this.IsValidMachineId(this.machineId);
}
}
一个bool型的返回值,嗯,interesting! IsNoCheck翻译过来就是没找到,参数传入的就是我们自己输入的所谓的注册码,返回值肯定就是false 或者true.
后面亦是如此
所以直接右键edit method (C#)或者快捷键 ctrl+shift+E,做出如下改动.
// Token: 0x1700000F RID: 15
// (get) Token: 0x060000FC RID: 252 RVA: 0x0000BC64 File Offset: 0x0000AC64
public bool IsRegistered
{
get
{
return true;
}
}
以防万一,再看一下IsRegistered的情形:
// Token: 0x060000B2 RID: 178 RVA: 0x000085AC File Offset: 0x000075AC
public static bool IsRegistered()
{
WLInstallInfo installInfo = WLInstallInfo.Create();
return installInfo.IsRegistered;
}
完美,这里又返回来调用上面那个method,所以get_IsRegistered就是真正的门啦~
破门而入成功~
做完上面的部分,基本上已经完成啦.
所以ctrl+shift+s直接保存~
现在打开你的word试试看吧~
成品
链接: http://pan.baidu.com/s/1c23W6L6 密码: 52pj
食用方法:解压压缩包,点击setup安装,然后把安装目录的word-to-latex-lib.dll替换为破解过的这个word-to-latex-lib.DLL
如果你对上面的分析还不满意,那么
以下注册码均可直接注册,邮箱随意,请放心食用
如果你想知道怎么来的,跟着这个简单的教程一起来做做看吧~
DIXXE-1UKJP-3ST8L-VQV1I-WNFD3
1SBNS-K2AHY-NIT92-IBUBJ-F6AB7
S7V7K-Y8D9W-5UXFC-V4UPC-W7NRH
87NHH-U9PQG-9NNLW-JQQG6-2C9W2
KT89J-QGRDX-887WX-N6KCR-HVH8C
MAPV6-QGZYP-JN6A1-4I9BE-7YJRB
B96SG-IFQ8A-WYQVW-FEJLP-KQ7T1
LZZ6R-AGZG9-FZN67-Y25NW-14BKQ
Z5F7X-GSXFY-NQFN6-N46C9-DAAHY
7I3I3-SI87Q-5NH34-GQTVE-ZIH5V
QH51Z-48I6R-LX9T5-YYSG1-VWRPR
5NAMT-6CAAD-ADKSI-BEGK7-LJ6E1
79WXY-N3LYP-E42PE-EZSZS-BB6RV
DDFIR-FP1CM-YZPJY-EY3FN-GTM8S
EJ3JB-YXNEF-ET5E5-RC5GW-3UV59
JL36U-UJDX4-NW1CA-GQ4K5-8CGCS