PHP7中用opcache.file_cache导出脚本opcode实现源代码保护
http://my.oschina.net/eechen/blog/539995
下载PHPDroid: 基于WebView和PHP内置HTTP服务器开发Android应用
http://my.oschina.net/eechen/blog/655689
截图是我在Ubuntu上用arm-none-linux-gnueabi-gcc交叉编译的Android版PHP(静态链接glibc等库).
adb push ./php /data/local/tmp 上传到Android系统(小米4),直接 ./php -S 127.0.0.1:8181 跑Web服务.
套个WebView就能用PHP(内置Web服务器和SQLite引擎)写Android应用了.
生成的php用arm-none-linux-gnueabi-strip去掉符号表,zip压缩后约5MB.
少用些图片,整个应用做到8MB以内应该没什么问题.
http://my.oschina.net/eechen/blog/298027
HHVM和PHP7都已经发出来了,还有具体的编译打包方法,可以自行按照教程构建出Nginx/Apache/MySQL,至于Android版PHP的交叉编译构建,参考的是DroidPHP的方法.
我的Android App也基本写好了,已经跑在我的小米4上了.
过程就是把/data/app/net.php.phpdroid.apk/assets/php/复制到/data/data/net.php.phpdroid/php/,
然后Java exec调用/system/bin/sh执行命令,先给php/bin/start.sh赋予执行权限,然后执行start.sh,
start.sh里给php/bin/php赋予执行权限,然后调用php生成用于标记WebView的UserAgent的随机串php/bin/ua,
并调用php的fsockopen从8181开始在127.0.0.2上找到可用的端口php/bin/port,
然后启动PHP的HTTP服务器,然后用echo $! > php/bin/pid记录PHP的PID,
start.sh执行完后回到Java主程序,主程序读取UserAgent(php/bin/ua)并setUserAgentString和
读取端口(php/bin/port)并loadUrl,从而打开WebView并访问本地PHP.
退出关闭的时候则执行stop.sh调用kill杀死php/bin/pid.
start.sh的开头也执行一次stop.sh,关掉可能没有被杀死的旧进程.
补充一下User Agent验证的说明:
/data/data/net.php.phpdroid/php/bin/php \
-c /data/data/net.php.phpdroid/php/bin/php.ini \
-S 127.0.0.2:8181 \
-t /data/data/net.php.phpdroid/www \
/data/data/net.php.phpdroid/php/auth.php
其中auth.php是PHP内置的HTTP服务器的特性,就是每个请求都会经过auth.php处理.
名字不要求是auth.php,可以随意取,加到php启动参数里就能生效.
https://wiki.php.net/rfc/builtinwebserver
<?php
//return false;
$ua = file_get_contents(dirname(__FILE__).'/ua');
if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']===$ua) return false;
else exit('Auth Failed');
代码意思就是如果客户端User Agent不是/data/data/net.php.phpdroid/bin/ua,则拒绝访问.
等我整理好,我会把这些资源全都放出来,授人以鱼也应该授人以渔,
这些知识都是从网络上获得的,如果每个人都藏着掖着,那我也不会捕鱼,
正是因为有的人乐于分享,知识才得以广泛传播.
像patchelf便携式打包参考的就是百度技术博客的分享:
http://lamp.baidu.com/2014/10/17/gou-jian-ke-sui-di-bu-shu-de-lampji-chu-huan-jing-bao/
构建Android版PHP参考的则是DroidPHP的分享:
https://github.com/DroidPHP/DroidPHP/blob/master/docs/Compiling.md
Linux上,用tar.xz打包GCC -O3编译的php7cli(3MB)和依赖库php7libs(7MB),大小约10MB.
因为打包了依赖库,所以能做到解压即用,适配所有Linux发行版.
整个应用打包下来,可以做到不超过15MB.
如果源代码不想被别人看到,PHP7支持用opcache.file_cache导出脚本opcode实现源代码保护,详情看:
http://my.oschina.net/eechen/blog/539995
我打包了适用于64位Linux的PHP7:
http://my.oschina.net/eechen/blog/411534
去掉里面的PHP-FPM和PHP-CGI,保留PHP CLI,整个PHP7环境就是10MB左右了.
假设应用安装在/png/php/7.0.0,其下的www作为根目录,启动HTTP服务:
/png/php/7.0.0/bin/php -S localhost:9393 -t /png/php/7.0.0/www
浏览器做界面,访问localhost:9393打开应用.
这两个步骤可以做成一个启动脚本start.sh:
#!/bin/bash
nohup /png/php/7.0.0/bin/php -S localhost:9393 -t /png/php/7.0.0/www >/dev/null 2>&1 &
nohup xdg-open http://localhost:9393/ >/dev/null 2>&1 &
关闭脚本stop.php就更简单了,调用kill关闭PHP CLI进程即可:
<?php
shell_exec('kill '.getmypid());
比如PHP调用系统自带命令lshw或者读取/proc/cpuinfo就能拿到各种硬件信息,包括CPU的即时运行频率等.
PHP可以把命令返回的信息直接写在
这样,像 雅黑探针 那样,通过Web界面就能获取像Windows上CPU-Z工具的硬件信息.
Linux"一切皆文件"的思想方便PHP获取系统信息开发Linux桌面应用.
/proc和/sys这两个文件系统里包含了Linux的各种运行时信息和硬件信息.
通过man proc查查每项的说明,任何语言都能以文本形式访问里面的数据,比如PHP获取内存使用信息:
<?php
$arr = explode("\n", file_get_contents('/proc/meminfo'));
foreach($arr as $k => $v) {
if(!empty($v)) {
$tmp = explode(':', $v);
$new[trim($tmp[0])] = trim($tmp[1]);
}
}
echo 'MemTotal: '.$new['MemTotal']."\n";
echo 'MemFree: '.$new['MemFree']."\n";
echo 'Buffers: '.$new['Buffers']."\n";
echo 'Cached: '.$new['Cached']."\n";
echo 'SwapCached: '.$new['SwapCached']."\n";
本地存储用SQLite,浏览器跟本地和服务器交互可以用AJAX或者WebSocket(Swoole),
程序更新时pclose(popen('upgrade.php', 'r'))打开一个CLI进程用file_get_contents()或者curl获取更新包.
进程间可以通过文件系统标记或者SQLite数据库进行通信.
CodeSourcery基于GNU GCC改造的交叉编译器 arm-none-linux-gnueabi 编译的程序能兼容多种ARM架构.
在Linux上把PHP移植到Android上运行的DroidPHP项目就用到了 arm-none-linux-gnueabi-gcc 这个交叉编译器:
https://github.com/DroidPHP/DroidPHP/blob/master/docs/Compiling.md
把PHP部署到客户端Android,WebView做界面,这样用网站开发技术HTML/CSS/JS/PHP/SQL就能够开发Android应用.
DroidPHP编译教程里面有一些小错误,比如:
LDFLAGS="-static -I$ROOTFS/lib -L$ROOTFS/usr/lib" \
应该改为:
LDFLAGS="-static -L$ROOTFS/lib -L$ROOTFS/usr/lib" \
还有应该使用arm-none-linux-gnueabi的头文件,比如:
mv /png/dev/android/glibc/usr/include /png/dev/android/glibc/usr/include_backup
ln -s /png/dev/android/arm-2014.05/arm-none-linux-gnueabi/libc/usr/include /png/dev/android/glibc/usr
因为PHP默认调用/bin/sh来执行命令,而Android上没有/bin/sh,只有/system/bin/sh.
所以交叉编译前需要把/bin/sh该为/system/bin/sh:
sed -i "s{/bin/sh{/system/bin/sh{" ext/standard/proc_open.c