HTML5在IOS设备中上传图片旋转问题

最后做龙湖的晒基因微信游戏,遇到蛋疼的问题,IOS设备中上传的图片不是正的,导制人脸无法识别,经过大半天的折腾终于解决

人脸识别接口:

http://www.faceplusplus.com.cn/demo-detect/

PHP中需要用EXIF来获取图片信息,来决定是否旋转把图片摆正

安装php_exif组件

要安装php_exif组件,首先我们还是要打开php源码安装文件夹中的ext/exif,命令如下(具体路径以你服务器实际地址为准)

1
2
3
4
5
6
7
cd /usr/local/src/php-5.4.8/ext/exif
/opt/php/bin/phpize
./configure --with-php-config=/opt/php/bin/php-config
 
make && make install

安装完毕之后,你需要将php_exif扩展添加到php.ini文件中

1
2
3
vi /opt/php/lib/php.ini
#找到extension列表中  添加一行  extension=exif.so

然后重启下php-fpm,再去phpinfo函数中查看下exif组件是否存在了。

 

$exif= exif_read_data ($img,"IFD0");

用这句话来获得EXIF信息

图片旋转的函数

/**
  * 修改一个图片 让其翻转指定度数
  *
  * @param string  $filename 文件名(包括文件路径)
  * @param  float $degrees 旋转度数
  * @return boolean
  * @author zhaocj
  */
   function  flip($filename,$src,$degrees = 90)
 {
  //读取图片
  $data = @getimagesize($filename);
  if($data==false)return false;
  //读取旧图片
  switch ($data[2]) {
   case 1:
    $src_f = imagecreatefromgif($filename);break;
   case 2:
    $src_f = imagecreatefromjpeg($filename);break;
   case 3:
    $src_f = imagecreatefrompng($filename);break;
  }
  if($src_f=="")return false;
  $rotate = @imagerotate($src_f, $degrees,0);
  if(!imagejpeg($rotate,$src,100))return false;
  @imagedestroy($rotate);
  return true;
 }

EXIF Orientation 参数让你随便照像但都可以看到正确方向的照片而无需手动旋转(前提要图片浏览器支持,Windows 自带的不支持)

旋转角度 参数
1
顺时针90° 6
逆时针90° 8
180° 3

参考文章:

http://blog.csdn.net/happy08god/article/details/11528479

http://www.markdream.com/technologies/programs/php-get-the-picture-exif-info.shtml

发表在 php | 留下评论

【转】如何做好微信营销?

万能公式:曝光X点击率X转化率X客单价=销售额 ,当然要再补充一个回头客,曝光x点击率就是流量,简化公式其实就是:流量X转化率X客单价=销售额!一切营销为让这几个数值的最大化最快化!一会雷军出来讲讲互联网思维,一会周鸿祎出来讲讲,大家所看到的都是他们提到的一些点,必然越看越有道理越看越晕。我感觉是故意的…回归万能公式,你就是清醒的人…

用问答来随便聊聊吧

一.微信产品的各自作用?

1.微信个人号:朋友圈转化变现

2.微信公众号:传播吸引粉丝+向个人号输送粉丝

简单的说你要卖产品变现,肯定是在个人微信号上,而不是在公众账号!

 二.微信赚钱有几个模式?

1.个人微信朋友圈卖产品:最普遍的模式,最低门槛的模式

2.分销裂变卖产品模式:千万级亿级利润模式,不过在2014下半年走下坡路。

1). 为什么有人可以在微信上卖面膜卖到上亿?分销机制,分级代理,链式核爆反应,每层代理都有不错的利润,发动群众的力量,当群众有利可图的时候,会歇斯底里宣传你的产品,哪怕他从来没用你的产品,当有人攻击你的产品的时候也会影响他的利益,他也会站起来歇斯底里的维护。其实他们真的懂产品的内幕吗?微信上95%女性产品是涉及虚假宣传的,号称进口的产品90%以上是国内小作坊的,价格200左右的产品大部分成本是30元以内的,很多产品包装盒成本是大于产品成本的,很多所谓神器是论桶算钱的…

2).微信分销能否核爆的一个关键命门是:定价!3倍4倍以上成本定价(不封上限,10倍20倍也有)你才能核爆,很遗憾,很多所谓微信营销的大师并不明白。只有这样的定价才能保证各级代理商的疯狂!原始驱动力!

3).各种模特产品图和见证图去淘宝和威客平台去找,一般都在50元内,包括所谓的尼玛模特

4).针对所有代理商不断培训引流技巧和说假话技巧和执行标准化,无限降低大脑思考门槛,小代理商只需要不断复制上级的朋友圈图片和文字就ok

5).上级代理想尽办法洗脑让下级代理商囤货,货出了钱就赚了,小代理商死活与他们无关

6).这个品牌做死了,ok,换个名字继续来

以下括号内容为某位仁兄总结的微信坑爹洗脑大法,接招:((
1:多个微信号运营。

2:自说自话,对话截图,使用效果突出。

3:自说自话,多人求代理名额截图,突出代理名额紧张

4:自说自话,如做了一个月的小雪,销售火爆要紧急拿货,呵呵

5:自说自话,客户不仅自己用的好,还推荐朋友购买……………..

6:自说自话,编各种故事,如多发了一盒客户补款

7:朋友圈各种晒。晒使用效果对比照片,晒订单截图,收款截图,发货照片,存货照片(所有代理公用)

8:故事化,情节化,刚发了100箱,进门还没喘口气,亲们谁又打款了,38笔,都没有注明是谁,快给地址和电话,快递要下班了,呵呵………

9:下月涨价通知

10:洗.脑—针对招代理,你还在犹豫,别人已经成功,等等;针对顾客—不贴面膜的女人没有前途的,面膜贴的好,老公回家早,呵呵

11:终于提车了,梦想重的MINI…….

))

对于朋友分销产品模式,我想说:尼玛,这是玩弄人性最恶的营销!

其实微信朋友圈分销模式的本质是,毛爷爷说过的话:发动群众的力量!

3.微信公众号收广告费:前几天刚有一个哥们在一个公众平台投了篇广告,1.9万一篇,你敢说公众平台账号盈利不行吗?PS:这块可以单独拿一篇讲,如果大家赞和转载热情的话,可以再开一篇…

 三.微信卖什么产品好?

产品实在不想说了,任意产品都可以在微信上卖,是的,任意!当然越暴利越好,越暴利意味着你可以玩随意的流量管道,随意任性的砸钱生钱!

 四.微信好友怎么来?这是所有玩微信营销的人卡壳的地方!

铁律1:必须是别人加你,而不是你加别人

铁律2:微信个人号朋友圈营销必然是精准营销,加过来的人必须是精准客户群体!不精准没有意义!

让别人主动加你的原理是?

在营销中利用人性最多的弱点是:贪,占便宜!人性中最薄弱的就是贪!所谓的占便宜!让看到的人觉得加你微信可以免费或者贪便宜得到某种东西,就ok了!当然如果你的微信号已经做出个人品牌,不用任何诱惑也可以一堆一堆人加你,这个后面说流量价值的时候说!

1步.分析你的产品使用群体:性别+年龄+职业划分+痛点

2步.分析你的产品购买群体:有些时候购买群体人和使用产品人是不一样的,比如脑白金使用客户是父母购买客户是儿女…购买群体消费能力+购买驱动点

3步.分析你的购买客户群体在哪里:百度?QQ群?淘宝?微信?社区?下面具体讲…

4步.锁定群体所在鱼塘后,用软文等载体来大规模曝光,用占便宜来吸引加微信!

 五.整个互联网最大流量池和最大的流量入口在哪里?

1.百度系:

免费玩法:搜索关键词的背后是一批有需求的人群。如果你的产品利润一般,那么尽量做免费流量!想办法来占关键词排名,短期排名来的最快,批量化百度霸屏!可以用以下高权重平台快速批量海量做排名:百度经验做排名,百度百家做排名,百度贴吧做排名,百度知道做排名,百度文库做排名,天涯做排名,豆瓣做排名,分类信息平台做排名,新闻源网站做排名,新浪博客网易博客,宝宝树妈妈帮做排名,知乎网做排名,ku6等视频平台做排名,腾讯微博新浪微博做排名,批量QQ空间做关键词排名…太TM多高权重平台,对于竞争不大的词做了就上去,然后批量就是了。

付费玩法:如果你的产品利润足够大,那么百度竞价就直接沦落为加微信好友流量入口,成交放在微信来解决!Why?百度竞价页面是钓鱼,鱼越来越难钓了;加到微信好友,用朋友圈慢慢养鱼!

2.淘宝系:

呵呵,这个不想多说,把淘宝系购买需求流量引到微信,马云大神知道了会不高兴…

3.腾讯QQ系:

主要指QQ群,QQ群是共同兴趣人聚集的流量窝,可以和群主搞好关系合作,也可以自己布局QQ群群主后面再营销,也可以导出QQ群群成员作为精准数据源。

我这边几万个数据QQ,每个QQ有100到200好友,然后克隆大号来玩产品,这是年利润百万级玩法,这个东西我本不该说,所以我就不深说了。最近小马哥也怒了,限制严格了…

4.腾讯微信系:

每个个人微信号都有自己的朋友圈好友,每个个人微信号都是个小媒体小电台,怎么发动这些海量小媒体来为自己微信号拉人?还记得上面说的吗?贪占便宜。转发到朋友圈这个信息并截图送什么什么…

微信公众平台号也是兴趣人群的流量池,在微信公众平台投软文广告引导到微信成交,这个也本不该说,所以也不深说,如果你非要测试我只能提醒你一定谨慎,因为我测试这个也是被骗了很多钱的,而且成本越来越高。但是这是月百万级利润玩法!

5.垂直社区群体系:

典型代表还是妈妈帮宝宝树世纪佳缘,特定兴趣大流量社区还是很多的,比如车论坛,宠物论坛,游戏论坛,户外论坛…等等。

问题在于用什么术来引流量到个人微信!无外乎2个手段:软文+群发!一个润物细无声一个简单粗暴,不愿意行动的人是永远有理由找不到方法的,别老想着让别人把饭喂到你嘴里…

6.视频系:
由于优酷和百度的官司纠纷,百度视频屏蔽了优酷视频,神仙打架殃及池鱼,洛阳这边哥们的海量优酷视频占百度视频流量入口的小百万级利润玩法无辜的死掉了,这个时代尼玛就是这样,就像三体里面一样:我毁灭你与你无关。各种躺枪…

海量优酷视频还可以玩,只是拿的是优酷平台本身流量,流量小了很多。海量ku6,搜狐,hao123影视还是可以蹭到不少百度精准流量的…

 六.流量与粉丝的区别?

上乘流量:个人品牌粉丝流量

优质流量:发生过一次关系的流量,简单的说有过第一次接触,可能是篇文章,可能是视频,可能是第三方人推荐,接触过你的信息后加你的微信

垃圾流量:完全不精准流量,自己胡乱主动加的流量,简单的说某个人微信在你微信好友里,但是他完全对你没有任何概念,或者他完全就不是你的客户群体范围

玩微信就完全不要考虑垃圾流量了,这种流量100个不顶一个粉丝流量或者一次关系流量

 七.为什么微信朋友圈营销赚钱好做?

1.微信朋友圈营销本质是数据库控制营销,比如有3000个好友我如果发了多条朋友圈信息,那么基本50%甚至70%以上微信好友是可以看到的,这是恐怖的强控,qqlist订阅和微信订阅号的点击率一般也就在10%到20%左右,弱控!

2.长期养鱼教育,长期见证,很强悍的转化

3.个人微信号的背后是人,天然的信任,客户犹豫的时候几句语音搞定

4.恐怖的群发功能完美的解决了节日的大促销

 八.微店?

坑爹货,忘记这玩意吧。很简单,问一下自己,你在微店买过东西吗?

以上所述皆非虚,都是自己玩过或者测过或者有哥们实例背书!
有点累,不写了…
最近大家都在喊各种不好做,我的看法刚好相反,越是大家认为不好做的时期赚钱越猛!淘宝是!竞价也是!微信更是!普遍难是因为属于变革转折点,越是变革期机会越大,乱世出英雄!

一定记住一个信念:所有事情都可以解决!所有事情都是简单的!如果你一直坚持这个信念,你做什么都是简单容易的,这就是心想事成,绝对100%有道理,后面解释给大家听。

淘宝也好,微信也好,百度也好,各种平台…你所需要的就是锁定一个领域往深处钻,钻的够深就是你的绝招!锁定1米宽挖100米深!

 万溪风光不同,终究同入大海!从一到万,从万到一!一切都是通的!一切都是简单的!

发表在 微信公众号 | 留下评论

解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误

配置公司内网服务器,启动nginx里启动不起来

提示错误:

nginx: [error] open() “/usr/local/nginx/nginx.pid” failed (2: No such file or directory)

解决办法:

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

使用nginx -c的参数指定nginx.conf文件的位置

发表在 linux | 留下评论

APP Store上架被苹果拒绝的奇葩理由汇总

2014年11月

我们的校园活动中,以IPHONE做为礼品,活动页入口在首页幻灯处,被拒绝后接口加了一个控制开关

2014年12月

我们的功能中,有邀请码功能,被拒绝后也是在接口中加了一个控制开关

发表在 IOS&OS | 留下评论

windows 下 PHP 使用 memcached

memcached 是一个高性能缓存,在网上搜的资料大部分是在 Linux 系统下使用的,windows 下面的介绍比较少,这里介绍一下 windows 系统下如何使用 memcached

需要的文件下载:http://download.csdn.net/detail/realghost/6581995

这里提供PHP5.2、5.3、5.4、5.5的php_memcache.dll扩展,需要的可以下载。http://pan.baidu.com/share/link?shareid=2718974422&uk=3978399093

下载解压后有 1 个 memcache 文件夹,里面包含 windows 系统使用的 memcached 服务端,x86 和 x64 分别对应 32 位版和 64 位版;还有一个 php_memcache.dll 文件,是 PHP 5.4 使用的扩展库。

把 memcached.exe 解压到本地硬盘,下面是 memcache 的常用操作及命令

安装:

memcached -d install

memcached -d start

net start “Memcached Server”

卸载:

memcached -d stop

memcached -d remove

sc delete “Memcached Server”

memcached的基本设置:

-p 监听的端口

-l 连接的IP地址, 默认是本机

-d start 启动memcached服务

-d restart 重起memcached服务

-d stop|shutdown 关闭正在运行的memcached服务

-d install 安装memcached服务

-d uninstall 卸载memcached服务

-u 以的身份运行 (仅在以root运行的时候有效)

-m 最大内存使用,单位MB。默认64MB

-M 内存耗尽时返回错误,而不是删除项

-c 最大同时连接数,默认是1024

-f 块大小增长因子,默认是1.25

-n 最小分配空间,key+value+flags默认是48

-h 显示帮助

memcached 服务安装成功后在任务管理器里可以看到 memcached 守护进程,在系统的服务中也应该能够看到相应的服务。

接下来配置 PHP

把 php_memcache.dll 拷贝到 PHP 的扩展文件夹, 在 php.ini 文件里添加一行

extension=php_memcache.dll

重启 web 服务器,查看 phpinfo,如果有 memcached 的内容,就说明 PHP 配置成功。

可以用以下程序测试是否安装成功:

  1. <?php  
  2. $memcache = new Memcache;  
  3. $memcache->connect(‘localhost’, 11211);  
  4. $memcache->add(‘key’, ‘This is a memcache value!’);  
  5.   
  6. echo $memcache->get(‘key’);  
  7. ?>  


PHP 中 memcache 对象的方法:

Memcache::add — 增加一个条目到缓存服务器
Memcache::addServer — 向连接池中添加一个memcache服务器
Memcache::close — 关闭memcache连接
Memcache::connect — 打开一个memcached服务端连接
Memcache::decrement — 减小元素的值
Memcache::delete — 从服务端删除一个元素
Memcache::flush — 清洗(删除)已经存储的所有的元素
Memcache::get — 从服务端检回一个元素
Memcache::getExtendedStats — 缓存服务器池中所有服务器统计信息
Memcache::getServerStatus — 用于获取一个服务器的在线/离线状态
Memcache::getStats — 获取服务器统计信息
Memcache::getVersion — 返回服务器版本信息
Memcache::increment — 增加一个元素的值
Memcache::pconnect — 打开一个到服务器的持久化连接
Memcache::replace — 替换已经存在的元素的值
Memcache::set — Store data at the server
Memcache::setCompressThreshold — 开启大值自动压缩
Memcache::setServerParams — 运行时修改服务器参数和状态

发表在 php | 留下评论

【转】redis在windows下安装和PHP5.4.X中使用

windows下安装redis

1、redis简介
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hashs(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。

2、windows下安装redis
下载地址https://github.com/dmajkic/redis/downloads。下载到的Redis支持32bit和64bit。根据自己实际情况选择,我选择32bit。把32bit文件内容拷贝到需要安装的目录下,比如:D:\dev\redis-2.4.5。

打开一个cmd窗口,使用cd命令切换到指定目录(D:\dev\redis-2.4.5)运行 redis-server.exe redis.conf 。运行以后出现如下界面。

这就说明Redis服务端已经安装成功。

重新打开一个cmd窗口,使用cd命令切换到指定目录(D:\dev\redis-2.4.5)运行 redis-cli.exe -h 127.0.0.1 -p 6379,其中 127.0.0.1是本地ip,6379是redis服务端的默认端口。运行成功如下图所示。
这样,Redis windows环境下搭建已经完成,是不是很简单。

这样,Redis windows环境下搭建已经完成,是不是很简单。

环境已经搭建好,总得测试下吧。比如:存储一个key为test,value为hello word的字符串,然后获取key值。

正确输出 hell word,测试成功!

 

3、PHP中使用

下载 dll文件

http://download.csdn.net/download/bluesky321/5355093

php_redis.dll 扩展 For PHP5.4.x

 

PHP5.4.x 的 redis 扩展 php_redis.dll

测试平台:Windows XPx32 (FastCGI PHP5.4.9 Nginx 1.4.0)

 

包含 Non Thread Safe 和 Thread Safe 两个版本

通过phpinfo(); 查看其中的 Thread Safety 项,这个项目就是查看是否是线程安全,如果是:enabled,一般来说应该是ts版,否则是nts版。

首先把php_redis.dll 和 php_igbinary.dll 放入PHP的ext文件夹,然后在php.ini配置文件里添加如下代码:

 

extension=php_igbinary.dll

extension=php_redis.dll

 

重启web服务器

 

注意:extension=php_igbinary.dll一定要放在extension=php_redis.dll的前面,否则此扩展不会生效

4、PHP中使用

代码如下

<?php
    $redis = new Redis();
    $redis->connect('127.0.0.1',6379);
    $redis->set('test','hello redis');
    echo $redis->get('test');
?>

输出 hello  redis 成功!

发表在 php | 留下评论

【转】linux下shell显示-bash-4.1#不显示路径解决方法

今天登录服务器莫名奇妙的显示-bash-4.1,度娘了一下,发现很多人出现过

 

在linux shell中不显示路径了,显示为-bash-4.1#用起来很不方便。

如何改为显示路径的shell呢?

步骤如下:

vim ~/.bash_profile

(不用管.bash_profile这个文件有几个,自己新建一个也是可以的)

在最后加上
export PS1='[\u@\h \W]\$’

然后执行
source ~/.bash_profile

这样shell就可以显示路径了。

发表在 linux | 留下评论

【转】INNODB: UNABLE TO LOCK ./IBDATA1, ERROR: 11 解决方法

错误日志中: InnoDB: Unable to lock ./ibdata1, error: 11 二进制日志中: Error writing file ‘/tmp/tmp….’ (Errcode: 28) 今天在看本地测试环境的时候发…

错误日志中: InnoDB: Unable to lock ./ibdata1, error: 11

二进制日志中: Error writing file ‘/tmp/tmp….’ (Errcode: 28)

今天在看本地测试环境的时候发现主备数据库中备用的数据库在读取的时候出现错误了,读取不到需要的内容,但是切换到主数据库就可以了,无奈….

进入备用的数据库一看,我去….   竟然刚建的表没有建立成功,什么情况…

先把数据库关了,重启一下试试….

关闭之后,再启动竟然启动不了了,一直处于正在启动中,一直显示…..  这可怎么搞也,我又不是专业的.

看看错误日志吧,看看能不能找到一些问题所在.

果然不出我所料,在错误日志中,启动的时候出现大量的信息,主要信息就只有一个.

01 InnoDB: Unable to lock ./ibdata1, error: 11
02 InnoDB: Check that you do not already have another mysqld process
03 InnoDB: using the same InnoDB data or log files.
04 InnoDB: Unable to lock ./ibdata1, error: 11
05 InnoDB: Check that you do not already have another mysqld process
06 InnoDB: using the same InnoDB data or log files.
07 InnoDB: Unable to lock ./ibdata1, error: 11
08 InnoDB: Check that you do not already have another mysqld process
09 InnoDB: using the same InnoDB data or log files.
10 InnoDB: Unable to lock ./ibdata1, error: 11
11 InnoDB: Check that you do not already have another mysqld process
12 InnoDB: using the same InnoDB data or log files.
13 InnoDB: Unable to lock ./ibdata1, error: 11
14 InnoDB: Check that you do not already have another mysqld process
15 InnoDB: using the same InnoDB data or log files.
16 InnoDB: Unable to lock ./ibdata1, error: 11
17 InnoDB: Check that you do not already have another mysqld process
18 InnoDB: using the same InnoDB data or log files.
19 InnoDB: Unable to lock ./ibdata1, error: 11
20 InnoDB: Check that you do not already have another mysqld process
21 InnoDB: using the same InnoDB data or log files.
22 InnoDB: Unable to lock ./ibdata1, error: 11
23 InnoDB: Check that you do not already have another mysqld process
24 InnoDB: using the same InnoDB data or log files.
25 InnoDB: Unable to lock ./ibdata1, error: 11
26 InnoDB: Check that you do not already have another mysqld process
27 InnoDB: using the same InnoDB data or log files.
28 InnoDB: Unable to lock ./ibdata1, error: 11
29 InnoDB: Check that you do not already have another mysqld process
30 InnoDB: using the same InnoDB data or log files.
31 InnoDB: Unable to lock ./ibdata1, error: 11
32 InnoDB: Check that you do not already have another mysqld process
33 InnoDB: using the same InnoDB data or log files.
34 InnoDB: Unable to lock ./ibdata1, error: 11
35 InnoDB: Check that you do not already have another mysqld process
36 InnoDB: using the same InnoDB data or log files.
37 InnoDB: Unable to lock ./ibdata1, error: 11
38 InnoDB: Check that you do not already have another mysqld process
39 InnoDB: using the same InnoDB data or log files.
40 InnoDB: Unable to lock ./ibdata1, error: 11
41 InnoDB: Check that you do not already have another mysqld process
42 InnoDB: using the same InnoDB data or log files.
43 InnoDB: Unable to lock ./ibdata1, error: 11
44 InnoDB: Check that you do not already have another mysqld process
45 InnoDB: using the same InnoDB data or log files.
46 InnoDB: Unable to lock ./ibdata1, error: 11
47 InnoDB: Check that you do not already have another mysqld process
48 InnoDB: using the same InnoDB data or log files.
49 InnoDB: Unable to lock ./ibdata1, error: 11
50 InnoDB: Check that you do not already have another mysqld process

InnoDB: Unable to lock ./ibdata1, error: 11

直接把这个错误信息弄到百度上,找到原因了,感谢度娘

要是你开启了二进制日志功能那么你会看见里边有

” Error writing file ‘/tmp/tmp….’ (Errcode: 28)”类似的内容,也是同样的原因造成的.

错误原因:

此错误信息是由于你的磁盘空间不足导致在mysql启动的时候无法正常的读写你data中的表的数据

用df -Th就能看见你现在的空间使用量了.

可以使用du -sh /*  来看一下那个路径下的文件比较大,删除一些无用的文件就好了.

PS:有时也不一定是空间不做造成的,不过你可以这样做

mysql进程图片

用kill -9 将这两个进程杀死.

然后用命令重新启动mysqld服务

1 service mysqld start

发表在 MYSQL | 留下评论

PHP程序下如何取得APK签名以及验证是否一致

Centos 环境

首先下载JDK :http://www.oracle.com/technetwork/java/javase/downloads/index.html

我用的是rpm包安装:rpm -ivh jdk-8u20-linux-x64.rpm

配置环境变量:vi /etc/profile  加入以下行

export JAVA_HOME=/usr/java/jdk1.8.0_20
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin

要让配置生效执行:source /etc/profile

以下代码可以获取MD5

[root@web-1 1]# unzip -p express.apk META-INF/CERT.RSA | keytool -printcert | grep MD5
MD5: 19:2A:5C:11:3E:72:A0:A1:A1:10:A3:BE:C3:9C:D5:32
[root@web-1 1]# unzip -p express.apk META-INF/CERT.RSA | keytool -printcert | grep SHA1
SHA1: 91:83:AF:08:B5:00:88:85:E6:4C:E9:41:4E:3B:06:EC:51:E8:F8:83
Signature algorithm name: SHA1withRSA

 

发表在 Android | 留下评论

【转】 php上传apk后自动提取apk包的信息

去年加入宝龙达的软件与增值产品部门,进入公司第一个项目就是做market市场。所以后台要上传APK软件之类。为了方便,上传APK后由系统自动提取APK文件的相关信息,比如:apk包名、产品名称、版本信息、APK Code、程序大小、ICON等。

起初处理方式

通过命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter.xml
得到cmdAfter.xml文件,然后分析cmdAfter.xml文件获取相关信息。

但是遗憾的是,从这文件中可以得到apk包名,但无法得到ico图标文件名及其它相关信息。如下图所示

上图中,比如label、icon等都是标志值,无法直接得到需要的结果。曾经分析该值与APK文件内部文件的关系,但不同的APK构造不同,实现过于麻烦。事实上,网上一些安桌市场等网站,当你上传APK时,除了提取出APK包名外,还包括ICON图标、大小等信息。因此,即然别人可以实现,我想肯定有办法来解决这个事情。于是经过研究,得到预期结果。在此将方法做个记录,欢迎交流。

核心提取APK信息代码

  1. /*** 
  2.  * 分析已上传的APK文件,提取所需要的数据 
  3.  */  
  4. function upAPK(){  
  5.   global $_config_product_apktool_count;//使用apktool.jar解压的次数,原因下面有说明。  
  6.   if($this->msg!=)return;//如果有错误,返回  
  7.   $dir=$this->upload_path;//上传路径  
  8.   $stringsXML_exists=false;  
  9.   if(file_exists($dir.‘package/res/values/strings.xml’))unlink($dir.‘package/res/values/strings.xml’);  
  10.   for($i=0;$i<$_config_product_apktool_count && !$stringsXML_exists;$i++){  
  11.     //针对UC的APK包或其类似的APK包,解压一次并不能完全得到strings.xml文件或相关文件。目前只有采用这个办法了。  
  12.     //在系统cmd下直接使用java -jar …执行解压,有时可以得到strings.xml文件,有时也得不到,不知道是不是jar包的问题。  
  13.     exec(‘java -jar ../apktool.jar d -f ‘.$this->tmpFile.‘ ‘.$dir.‘package’);//注释:解压完毕再往下执行  
  14.     $stringsXML_exists=file_exists($dir.‘package/res/values/strings.xml’);  
  15.   }  
  16.   //检查AndroidManifest.xml文件是否存在,如果不存在,则不是合法的APK文件  
  17.   if(!file_exists($dir.‘package/AndroidManifest.xml’)){$this->msg=‘不是合法的APK文件,请重新上传!’;return;}  
  18.   $AndroidManifestXML=file_get_contents($dir.‘package/AndroidManifest.xml’);//读取AndroidManifest.xml  
  19.   
  20.   if(preg_match(‘/package=\”([^\”]*)\”/i’,$AndroidManifestXML,$package))$returnVal[‘package’]=$package[1];//如果有包名,返回到数组  
  21.   
  22.   //增加versionCode  
  23.   if(preg_match(‘/versionCode=\”([^\”]*)\”/i’,$AndroidManifestXML,$versionCode))$returnVal[‘versionCode’]=$versionCode[1];//如果有版本代码,返回到数组  
  24.   
  25.   //检测到包名后判断数据库中是否已经存在。  
  26.   if($this->id==0){//添加新产品时检测,修改产品不检测  
  27.     if($returnVal[‘package’]!=){  
  28.       $sql=‘select id from product where package=’.SqlEncode($package[1]);  
  29.       $result=mysql_query($sql);  
  30.       if(mysql_num_rows($result)>0){  
  31.         $this->msg=‘该APK已经存在,请更换!’;  
  32.         return;  
  33.       }  
  34.     }else{  
  35.       $this->msg=‘系统无法检测该APK信息,请联系管理员!’;  
  36.       return;  
  37.     }  
  38.   }  
  39.   
  40.   if($stringsXML_exists)$stringXML=file_get_contents($dir.‘package/res/values/strings.xml’);//如果有strings.xml则读取strings.xml文件  
  41.   if(preg_match(‘/versionName=\”([^\”]*)\”/i’,$AndroidManifestXML,$ver))$returnVal[‘ver’]=$ver[1];//如果有版本号,返回到数组  
  42.   //版本号的情况目前发现有两种:1、版本号在AndroidManifest.xml中直接列出;通过以上正则即可提取  
  43.   //2、版本号同label一样,放到strings.xml文件中  
  44.   //2011-11-23 add  
  45.   if($stringXML!= && strstr($ver[1],‘@’)){  
  46.     if(preg_match(‘/^@string\/(.*)/i’,$ver[1],$findVer)){  
  47.       if(preg_match(‘/<string name=\”‘.$findVer[1].‘\”>([^<]*)<\/string>/’,$stringXML,$a))$returnVal[‘ver’]=$a[1];  
  48.     }  
  49.   }  
  50.   ////////////////////////////////////////////  
  51.   if(preg_match(‘/<application[\s\S]*? android:icon=”@drawable\/([^”]*)”/i’,$AndroidManifestXML,$icon))$returnVal[‘thumbimg’]=$icon[1];//如果有图标,返回到数组  
  52.   if($stringsXML_exists && preg_match(‘/<application[\s\S]*? android:label=”@string\/([^”]*)”/i’,$AndroidManifestXML,$label)){  
  53.     if(preg_match(‘/<string name=\”‘.$label[1].‘\”>([^<]*)<\/string>/’,$stringXML,$name)){  
  54.       $returnVal[‘name’]=$name[1];//如果有产品名称,返回到数组  
  55.       /** 
  56.       百度:strings.xml 
  57.       特殊情况1:<string name=”app_name”>”  掌上百度  “</string> 
  58.       */  
  59.       $returnVal[‘name’]=preg_replace(‘/\s|”/’,,$returnVal[‘name’]);  
  60.     }  
  61.   }  
  62.   //$this->msg=$returnVal[‘package’].’–‘.$returnVal[‘ver’].’–‘.$returnVal[‘thumbimg’].’–‘.$returnVal[‘name’];  
  63.   if($this->oldAPK!=){//重新上传则删除原apk文件和icon.png图片  
  64.     unlink($dir.$this->oldAPK);  
  65.     unlink($dir.$this->oldAPK.‘.png’);  
  66.   }  
  67.   //遍历package/res目录下的目录[drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi]  
  68.   //系统取icon尺寸最大的图标  
  69.   $tmpArr[0]=0;$tmpArr[1]=0;$tmpArr[2]=‘drawable’;  
  70.   $dirs=opendir($dir.‘package/res’);  
  71.   while(($file=readdir($dirs))){  
  72.     preg_match(‘/(drawable(-.*?dpi)?)/i’,$file,$drawable_folder);  
  73.     $iconPath=$dir.‘package/res/’.$drawable_folder[1].‘/’.$returnVal[‘thumbimg’].‘.png’;  
  74.     if(file_exists($iconPath)){  
  75.       $iconInfo=getimagesize($iconPath);  
  76.       if($iconInfo[0]>$tmpArr[0] && $iconInfo[1]>$tmpArr[1]){  
  77.         $tmpArr[0]=$iconInfo[0];$tmpArr[1]=$iconInfo[1];$tmpArr[2]=$drawable_folder[1];  
  78.       }  
  79.     }  
  80.   }  
  81.   //$this->msg=$iconInfo[0].’—‘.$iconInfo[1];  
  82.   closedir($dirs);  
  83.   if(rename($dir.‘package/res/’.$tmpArr[2].‘/’.$returnVal[‘thumbimg’].‘.png’,$dir.$this->iframe_key.‘.apk.png’)){//找到目录并成功移动  
  84.     $returnVal[‘thumbimg’]=$this->iframe_key.‘.apk.png’;  
  85.   }  
  86.   if(!move_uploaded_file($this->tmpFile,$dir.$this->iframe_key.‘.apk’)){$this->msg=‘上传失败!’;return;}//转移apk文件  
  87.   $returnVal[‘filename’]=$this->iframe_key.‘.apk’;  
  88.   $returnVal[‘size’]=$this->size;  
  89.   $this->result=$returnVal;  
  90. }  

提取信息流程

1、首先,通过apktool.jar命令提取apk文件中package/res/values/string.xml文件。不知为什么原因,释放apk文件时,有时并不一定得到string.xml文件。所以,后台增加:$_config_product_apktool_count参数,来控制释放的最大次数。

2、读取释放根目录下的AndroidManifest.xml文件。从该文件中可以获取到APK包名、版本信息。

3、检测,如果是新上传的APK,则其包名在数据库中是否存在。就是禁止上传相同包名的APK。修改时不检测。

4、通过正则获取所需要的信息。

这里为什么要提取string.xml文件?

因为并不是所有信息,都在AndroidManifest.xml中。有的信息在AndroidManifest.xml中只是做为一个“引用”,真实记录是在string.xml中的。比如

AndroidManifest.xml中关于Label和icon的值。

上图中:label=”@string/app_name” 表明在string.xml中string的name属性为app_name的值,即为该APK的“软件名称”,这里是“Market市场”,如下图所示:

@drawable/quickflick_icon,表示quickflick_icon为ICON的文件名。

由于特殊需要,我需要找到最大的ICON图标,见下面代码:

  1. //遍历package/res目录下的目录[drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi]  
  2. //系统取icon尺寸最大的图标  
  3. $tmpArr[0]=0;$tmpArr[1]=0;$tmpArr[2]=‘drawable’;  
  4. $dirs=opendir($dir.‘package/res’);  
  5. while(($file=readdir($dirs))){  
  6.   preg_match(‘/(drawable(-.*?dpi)?)/i’,$file,$drawable_folder);  
  7.   $iconPath=$dir.‘package/res/’.$drawable_folder[1].‘/’.$returnVal[‘thumbimg’].‘.png’;  
  8.   if(file_exists($iconPath)){  
  9.     $iconInfo=getimagesize($iconPath);  
  10.     if($iconInfo[0]>$tmpArr[0] && $iconInfo[1]>$tmpArr[1]){  
  11.       $tmpArr[0]=$iconInfo[0];$tmpArr[1]=$iconInfo[1];$tmpArr[2]=$drawable_folder[1];  
  12.     }  
  13.   }  
  14. }  
  15. //$this->msg=$iconInfo[0].’—‘.$iconInfo[1];  
  16. closedir($dirs);  

经过分析,一般APK中存放ICON图标在以下几个目录:drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi,通过遍历比较的方式获取最大ICON图标,并移到临时目录。

将所有需要提取的信息,存到一个数组中,并通过javascript写到表单中。如下图所示:

提取APK信息总结

上面的代码,目前为止,在提取上传的APK中,能能正常提取信息,未发现错误。在上面代码的注释中也看到,关于“掌上百度”这款APK,提取不了信息,是由于他的特殊处理方式,即:<string name=”app_name”>”  掌上百度  “</string>,他在名称中加上了双引号,这算是一个特例了吧。更多的特例我目前还未发现,所以,有可能会有特例出现,这需要分析APK的数据,并在程序中做特殊处理。

在实现这个APK提取功能中,关键是要找到APK包的组织规律,只有找到规律,程序实现就是在自然不过的事。

释放APK文件注意内容

exec(‘java -jar ../apktool.jar d -f ‘.$this->tmpFile.’ ‘.$dir.’package’);

能顺利执行上面的语句,要符合下面条件:

1、安装java包,对java目录,users用户组的权限有:读取和运行、列出文件夹目录、读取

2、cmd.exe文件,users用户组的权限有:读取和运行、读取

3、PHP允许调用exec

4、上传目录要确保有写入文件的权限

如果有更好的提取方式,欢迎交流,相互学习。

PHP提取APK信息DEMO演示下载

下载地址:http://download.csdn.net/detail/zm2714/4547459

发表在 Android | 留下评论