Skip to content

Instantly share code, notes, and snippets.

@iehong
Created September 11, 2013 09:53
Show Gist options
  • Save iehong/6521544 to your computer and use it in GitHub Desktop.
Save iehong/6521544 to your computer and use it in GitHub Desktop.
blog
This gist exceeds the recommended number of files (~10). To access all files, please clone this gist.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/blog.iml" filepath="$PROJECT_DIR$/.idea/blog.iml" />
</modules>
</component>
</project>
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
<?php
return array(
'DB_HOST'=>'127.0.0.1',
'DB_USER'=>'root',
'DB_PWD'=>'',
'DB_NAME'=>'iehong_blog',
'DB_PREFIX'=>'blog_',
//'配置项'=>'配置值'
'APP_GROUP_LIST'=>'Home,Admin',
'DEFAULT_GROUP'=>'Home',
'APP_GROUP_MODE'=>1,
'APP_GROUP_PATH'=>'Modules',
'URL_MODEL'=>2,
);
?>
<?php
Class CommonAction extends Action{
Public function _initialize(){
if(!isset($_SESSION['username'])){
$this->redirect(GROUP_NAME.'/Login/index');
}
}
}
?>
<?php
Class IndexAction extends CommonAction{
Public function index(){
$user=M('user')->where(array('username'=>$_SESSION['username']))->find();
$this->user=$user;
$this->display();
}
Public function bloglist(){
$blog=M('blog');
import('ORG.Util.Page');
$count=$blog->count();
$Page=new Page($count,17);
$show=$Page->show();
$list=$blog->order('updatetime desc')->limit($Page->firstRow.','.$Page->listRows)->select();
$this->list=$list;
$this->show=$show;
$this->display();
}
Public function deblog(){
M('blog')->where('id='.I('id'))->delete();
$this->redirect(GROUP_NAME.'/Index/bloglist');
}
Public function reblog(){
$this->blog=M('blog')->where('id='.I('id'))->find();
$this->display('newblog');
}
Public function newblog(){
$this->display();
}
Public function blog(){
$title=I('title');
$class=I('class');
$description=I('description');
$tag=I('tag');
$content=I('content');
$img='';
if($_FILES){
import('ORG.Net.UploadFile');
$config = array(
'supportMulti' => false, // 是否支持多文件上传
'allowExts' => array('png','jpg','gif','jpeg'), // 允许上传的文件后缀 留空不作后缀检查
'autoSub' => true,// 启用子目录保存文件
'subType' => 'date',// 子目录创建方式 可以使用hash date custom
'savePath' => './Uploads/thumb/', // 子目录名称 subType为custom方式后有效
'dateFormat' => 'Ym',
);
$upload= new UploadFile($config);
if($upload->upload()){
$info=$upload->getUploadFileInfo();
$img=__ROOT__.'/Uploads/thumb/'.$info[0]['savename'];
}
else die;
}
if(I('id')){
$data=array(
'title'=>$title,
'img'=>$img,
'description'=>$description,
'tag'=>$tag,
'content'=>$content,
'class'=>$class,
'updatetime'=>time(),
'id'=>I('id'),
);
}
else{
$data=array(
'title'=>$title,
'img'=>$img,
'description'=>$description,
'tag'=>$tag,
'content'=>$content,
'class'=>$class,
'updatetime'=>time(),
);
}
if(I('id')){
M('blog')->save($data);
$this->redirect(GROUP_NAME.'/Index/bloglist');
}
else if(M('blog')->add($data)){
$this->redirect(GROUP_NAME.'/Index/newblog');
}
}
Public function upimg(){
header('Content-Type: text/html; charset=UTF-8');
$inputName='filedata';//表单文件域name
$attachDir='./Uploads';//上传文件保存路径,结尾不要带/
$dirType=2;//1:按天存入目录 2:按月存入目录 3:按扩展名存目录 建议使用按天存
$maxAttachSize=2097152;//最大上传大小,默认是2M
$upExt='jpg,jpeg,gif,png';//上传扩展名
$msgType=2;//返回上传参数的格式:1,只返回url,2,返回参数数组
$immediate=isset($_GET['immediate'])?$_GET['immediate']:0;//立即上传模式,仅为演示用
ini_set('date.timezone','Asia/Shanghai');//时区
$err = "";
$msg = "''";
$tempPath=$attachDir.'/'.date("YmdHis").mt_rand(10000,99999).'.tmp';
$localName='';
if(isset($_SERVER['HTTP_CONTENT_DISPOSITION'])&&preg_match('/attachment;\s+name="(.+?)";\s+filename="(.+?)"/i',$_SERVER['HTTP_CONTENT_DISPOSITION'],$info)){//HTML5上传
file_put_contents($tempPath,file_get_contents("php://input"));
$localName=urldecode($info[2]);
}
else{//标准表单式上传
$upfile=@$_FILES[$inputName];
if(!isset($upfile))$err='文件域的name错误';
elseif(!empty($upfile['error'])){
switch($upfile['error'])
{
case '1':
$err = '文件大小超过了php.ini定义的upload_max_filesize值';
break;
case '2':
$err = '文件大小超过了HTML定义的MAX_FILE_SIZE值';
break;
case '3':
$err = '文件上传不完全';
break;
case '4':
$err = '无文件上传';
break;
case '6':
$err = '缺少临时文件夹';
break;
case '7':
$err = '写文件失败';
break;
case '8':
$err = '上传被其它扩展中断';
break;
case '999':
default:
$err = '无有效错误代码';
}
}
elseif(empty($upfile['tmp_name']) || $upfile['tmp_name'] == 'none')$err = '无文件上传';
else{
move_uploaded_file($upfile['tmp_name'],$tempPath);
$localName=$upfile['name'];
}
}
if($err==''){
$fileInfo=pathinfo($localName);
$extension=$fileInfo['extension'];
if(preg_match('/^('.str_replace(',','|',$upExt).')$/i',$extension))
{
$bytes=filesize($tempPath);
if($bytes > $maxAttachSize)$err='请不要上传大小超过'.formatBytes($maxAttachSize).'的文件';
else
{
switch($dirType)
{
case 1: $attachSubDir = 'day_'.date('ymd'); break;
case 2: $attachSubDir = 'month_'.date('ym'); break;
case 3: $attachSubDir = 'ext_'.$extension; break;
}
$attachDir = $attachDir.'/'.$attachSubDir;
if(!is_dir($attachDir))
{
@mkdir($attachDir, 0777);
@fclose(fopen($attachDir.'/index.htm', 'w'));
}
PHP_VERSION < '4.2.0' && mt_srand((double)microtime() * 1000000);
$newFilename=date("YmdHis").mt_rand(1000,9999).'.'.$extension;
$targetPath = $attachDir.'/'.$newFilename;
rename($tempPath,$targetPath);
@chmod($targetPath,0755);
$targetPath=__ROOT__.preg_replace("/([\\\\\/'])/",'\\\$1',$targetPath);
if($immediate=='1')$targetPath='!'.$targetPath;
if($msgType==1)$msg="'$targetPath'";
else $msg="{'url':'".$targetPath."','localname':'".preg_replace("/([\\\\\/'])/",'\\\$1',$localName)."','id':'1'}";//id参数固定不变,仅供演示,实际项目中可以是数据库ID
}
}
else $err='上传文件扩展名必需为:'.$upExt;
@unlink($tempPath);
}
echo "{'err':'".preg_replace("/([\\\\\/'])/",'\\\$1',$err)."','msg':".$msg."}";
function formatBytes($bytes) {
if($bytes >= 1073741824) {
$bytes = round($bytes / 1073741824 * 100) / 100 . 'GB';
} elseif($bytes >= 1048576) {
$bytes = round($bytes / 1048576 * 100) / 100 . 'MB';
} elseif($bytes >= 1024) {
$bytes = round($bytes / 1024 * 100) / 100 . 'KB';
} else {
$bytes = $bytes . 'Bytes';
}
return $bytes;
}
}
Public function about(){
$this->about=M('about')->limit(1)->select();
$this->display();
}
Public function newabout(){
$description=I('description');
$tag=I('tag');
$content=I('content');
$data=array(
'description'=>$description,
'tag'=>$tag,
'content'=>$content,
);
if(!M('about')->count()){
M('about')->add($data);
$this->redirect(GROUP_NAME.'/Index/about');
}
else{
M('about')->where('id=1')->setField($data);
$this->redirect(GROUP_NAME.'/Index/about');
}
}
Public function repwd(){
if(M('user')->where(array('username'=>$_SESSION['username']))->setField('password',I('password','','md5'))){
session_unset();
session_destroy();
$this->redirect(GROUP_NAME.'/Login/index');
}
}
Public function logout(){
M('user')->where(array('username'=>$_SESSION['username']))->setField('prelogintime',time());
session_unset();
session_destroy();
$this->redirect(GROUP_NAME.'/Login/index');
}
}
?>
<?php
Class LoginAction extends Action{
Public function index(){
$this->display();
}
Public function login(){
if(!IS_POST) halt('页面不存在');
if(md5(I('verify'))!=session('verify')) $this->error('验证码错误');
$user=M('user')->where(array('username'=>I('username')))->find();
if(!$user||$user['password']!=I('password','','md5')){
$this->error('帐号或密码错误');
}
session('username',$user['username']);
session('prelogintime',date('y/m/d H:i',$user['prelogintime']));
redirect(__GROUP__);
}
Public function verify(){
import('ORG.Util.Image');
Image::buildImageVerify();
}
}
?>
<?php
return array(
'URL_HTML_SUFFIX'=>'',
);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>blog</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
<script type="text/javascript" src='__ROOT__/xheditor/xheditor.min.js'></script>
<script type="text/javascript" src='__ROOT__/xheditor/xheditor_lang/zh-cn.js'></script>
</head>
<body>
<div id='in_box'>
<div id='blognew'>
<form method='post' action='{:U(GROUP_NAME.'/Index/newabout')}'>
<table class='table'>
<tr>
<td class='des' width='10%'>描述:</td>
<td class='des' colspan='3'><textarea class='des' name='description'>{$about[0]['description']}</textarea></td>
</tr>
<tr>
<td>标签:</td>
<td colspan='2'><input type='text' name='tag' value='{$about[0]['tag']}'></td>
<td class='submit'><input class='submit' type='submit' value='提交'></td>
</tr>
<tr>
<td class='content' colspan='4'><textarea class='xheditor' id='content' name='content'></textarea></td>
</tr>
</table>
</form>
</div>
</div>
<script type="text/javascript">
$('#content').xheditor({tools:'Img,Source',width:'615',height:'495',upImgUrl:"upimg"});
$('#content').val('{$about[0]['content']}');
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>blog</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
</head>
<body>
<div id='in_box'>
<table class='table'>
<tr>
<th width='60%'>标题</th>
<th width='10%'>浏览量</th>
<th width='30%'>操作</th>
</tr>
<foreach name="list" item="vo">
<tr>
<td>{$vo.title}</td>
<td align='center'>{$vo.count}</td>
<td align='center'>
<a href="{:U(GROUP_NAME.'/Index/reblog',array('id'=>$vo['id']))}">修改</a>
<a href="{:U(GROUP_NAME.'/Index/deblog',array('id'=>$vo['id']))}">删除</a>
<a target='_blank' href="{:U('/Index/pas',array('id'=>$vo['id']))}">查看</a>
</td>
</tr>
</foreach>
<tr>
<th align='center' colspan='3'>{$show}</th>
</tr>
</table>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>blog</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
</head>
<body>
<div id="box">
<div id="left">
<div id="adminsider">
<span>IEHONG</span>
<ul>
<li><a href="{:U(GROUP_NAME.'/Index/bloglist')}">查看博文</a></li>
<li><a href="{:U(GROUP_NAME.'/Index/newblog')}">发表博文</a></li>
<li><a href="{:U(GROUP_NAME.'/Index/about')}">修改关于</a></li>
<li><a class='pwd' href="">修改密码</a></li>
<li><a class='logout' href="{:U(GROUP_NAME.'/Index/logout')}">退出</a></li>
</ul>
<p>上次登录时间:{$user.prelogintime|date='y/m/d H:i',###}</p>
</div>
</div>
<div id="right">
<div class="admin_box">
<iframe scrolling="no" frameborder='no' width='620px' height='600px' src="">
</iframe>
<div id='repwd'>
<form method='post' action='{:U(GROUP_NAME.'/Index/repwd')}'>
<table class='table'>
<tr>
<td width='30%' align='right'>新密码:</td>
<td width='70%'><input class='password' type='password' name='password'></td>
</tr>
<tr>
<td width='30%' align='right'>确认密码:</td>
<td width='70%'><input class='repassword' type='password' name='repassword'></td>
</tr>
<tr>
<td colspan='2' align='center'><input class='submit' type='submit' value='提交'></td>
</tr>
</table>
</form>
</div>
</div>
</div>
<div class="clear"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>blog</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
<script type="text/javascript" src='__ROOT__/xheditor/xheditor.min.js'></script>
<script type="text/javascript" src='__ROOT__/xheditor/xheditor_lang/zh-cn.js'></script>
</head>
<body>
<div id='in_box'>
<div id='blognew'>
<form method='post' enctype='multipart/form-data' action="{:U(GROUP_NAME.'/Index/blog')}">
<input type='hidden' name='id' value='{$blog['id']}'>
<table class='table'>
<tr>
<td width='10%'>标题:</td>
<td width='60%'><input type='text' name='title' value='{$blog['title']}'></td>
<td width='15%' align='right'>分类:</td>
<td width='15%'>
<select name='class'>
<option <if condition="$blog['class'] == '项目' "> selected='selected' </if> value='项目'>项目</option>
<option <if condition="$blog['class'] == '技术汇总' "> selected='selected' </if> value='技术汇总'>技术汇总</option>
<option <if condition="$blog['class'] == '日常杂记' "> selected='selected' </if> value='日常杂记'>日常杂记</option>
</select>
</td>
</tr>
<tr>
<td class='des' width='10%'>描述:</td>
<td class='des' colspan='3'><textarea class='des' name='description'>{$blog['title']}</textarea></td>
</tr>
<tr>
<td width='10%'>缩略图:</td>
<td colspan='3'><input type='file' name='img'></td>
</tr>
<tr>
<td>标签:</td>
<td colspan='2'><input type='text' name='tag' value="{$blog['tag']}"></td>
<td class='submit'><input class='submit' type='submit' value='提交'></td>
</tr>
<tr>
<td class='content' colspan='4'><textarea class='xheditor' id='content' name='content'></textarea></td>
</tr>
</table>
</form>
</div>
</div>
<script type="text/javascript">
$('#content').xheditor({tools:'Img,Source',width:'615',height:'430',upImgUrl:"upimg"});
$('#content').val('{$blog["content"]}');
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>blog</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
<script type="text/javascript">
var VERIFY_URL='{:U(GROUP_NAME."/Login/verify")}/';
</script>
</head>
<body>
<div id='loginbox'>
<form method='post' action='{:U(GROUP_NAME.'/Login/login')}'>
<table class='table'>
<tr>
<td width='30%' align='right'>用户名:</td>
<td width='70%'><input type='text' name='username'></td>
</tr>
<tr>
<td width='30%' align='right'>密码:</td>
<td width='70%'><input type='password' name='password'></td>
</tr>
<tr>
<td width='30%' align='right'>验证码:</td>
<td width='35%'><input class='verify' type='text' name='verify'><img src="{:U(GROUP_NAME.'/Login/verify')}"></td>
</tr>
<tr>
<td colspan='2' align='center'><input type='submit' value='登录'></td>
</tr>
</table>
</form>
</div>
</body>
</html>
<?php
Class IndexAction extends Action{
Public function index(){
import('ORG.Util.Page');
$count=M('blog')->where('class != "项目"')->count();
$Page=new Page($count,6);
$Page->setConfig('prev', '<');
$Page->setConfig('next', '>');
$Page->setConfig('theme', ' %upPage% %first% %prePage% %linkPage% %nextPage% %end% %downPage%');
$show=$Page->show();
$list=M('blog')->where('class != "项目"')->order('updatetime desc')->limit($Page->firstRow.','.$Page->listRows)->select();
$this->list=$list;
$this->show=$show;
$this->class='';
$this->display();
}
Public function about(){
$this->about=M('about')->where('id=1')->find();
$this->display();
}
Public function liste(){
$condition['class']=I("class");
import('ORG.Util.Page');
$count=M('blog')->where($condition)->count();
if(I('class')=='项目') $Page=new Page($count,9);
else $Page=new Page($count,6);
$Page->setConfig('prev', '<');
$Page->setConfig('next', '>');
$Page->setConfig('theme', ' %upPage% %first% %prePage% %linkPage% %nextPage% %end% %downPage%');
$show=$Page->show();
$list=M('blog')->where($condition)->order('updatetime desc')->limit($Page->firstRow.','.$Page->listRows)->select();
$this->list=$list;
$this->show=$show;
$this->class=I('class');
if(I('class')=='项目') $this->display('item');
else $this->display('index');
}
Public function pas(){
$condition['id']=I('id');
$this->blog=M('blog')->where($condition)->find();
$this->display();
}
Public function count(){
$condition['id']=I('id');
M('blog')->where($condition)->setInc('count');
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>关于 | IEHONG</title>
<meta content="{$about.tag}" name="keywords">
<meta content="{$about.description}" name="description">
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
</head>
<body>
<div id="box">
<div id="left">
<div id="sider">
<img src="__PUBLIC__/images/head.jpg">
<ul>
<li><a href="__ROOT__">首页</a></li>
<li><a href="{:U('Index/liste',array('class'=>'项目'))}">项目</a></li>
<li><a href="{:U('Index/about')}">关于</a></li>
</ul>
<p>&copy; 2013 IEHONG</p>
</div>
<div id="ad">
</div>
</div>
<div id="right">
<div class="pas_box">
{$about.content}
</div>
</div>
<div class="clear"></div>
<div id="footer">
<a href="#">TOP</a><a target="_blank" href="mailto:iehong@qq.com">邮件</a><a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=630798273&site=qq&menu=yes">QQ</a><a target="_blank" href="http://t.qq.com/iehong_huang">微博</a><b>IEHONG</b>
</div>
<div id="cri">
<script src="http://v1.cnzz.com/stat.php?id=5643222&web_id=5643222" language="JavaScript"></script>
</div>
</div>
<div id='body_bg'></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>
<if condition='$class eq ""'>
IEHONG | Iehong是个人的技术博客,记录关于织梦,wordpress,php,前端开发的相关技术文章,并且包括个人的作品展示
<else/>{$class} | IEHONG
</if>
</title>
<meta content="wordpress,前端开发,织梦,php" name="keywords">
<meta content="Iehong是个人的技术博客,记录关于织梦,wordpress,php,前端开发的相关技术文章,并且包括个人的作品展示" name="description">
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
</head>
<body>
<div id="box">
<div id="left">
<div id="sider">
<img src="__PUBLIC__/images/head.jpg">
<ul>
<li><a href="__ROOT__">首页</a></li>
<li><a href="{:U('Index/liste',array('class'=>'项目'))}">项目</a></li>
<li><a href="{:U('/Index/about')}">关于</a></li>
</ul>
<p>&copy; 2013 IEHONG</p>
</div>
<div id="ad">
</div>
</div>
<div id="right">
<foreach name="list" item="vo">
<div class="item_pas">
<h3><span>{$vo.updatetime|date='Y/m/d',###}</span><a href="{:U('Index/pas',array('id'=>$vo['id']))}">{$vo.title}</a></h3>
<a class="thumb" href="{:U('Index/pas',array('id'=>$vo['id']))}"><img src="<if condition='$vo.img eq ""'>__PUBLIC__/images/noimg.jpg<else/>{$vo.img}</if>"></a>
<div class="intro">
<p>{$vo.description}</p>
<ul>
<li>{$vo.count}次浏览</li>
<li><a href="{:U('Index/pas',array('id'=>$vo['id']))}">查看更多</a></li>
</ul>
</div>
<div class="clear"></div>
</div>
</foreach>
<div id='paging'>{$show}</div>
</div>
<div class="clear"></div>
<div id="footer">
<a href="#">TOP</a><a target="_blank" href="mailto:iehong@qq.com">邮件</a><a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=630798273&site=qq&menu=yes">QQ</a><a target="_blank" href="http://t.qq.com/iehong_huang">微博</a><b>IEHONG</b>
</div>
<div id="cri">
<script src="http://v1.cnzz.com/stat.php?id=5643222&web_id=5643222" language="JavaScript"></script>
</div>
</div>
<div id='body_bg'></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>
<if condition='$class eq ""'>
IEHONG | Iehong是个人的技术博客,记录关于织梦,wordpress,php,前端开发的相关技术文章,并且包括个人的作品展示
<else/>{$class} | IEHONG
</if>
</title>
<meta content="wordpress,前端开发,织梦,php" name="keywords">
<meta content="Iehong是个人的技术博客,记录关于织梦,wordpress,php,前端开发的相关技术文章,并且包括个人的作品展示" name="description">
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
</head>
<body>
<div id="box">
<div id="left">
<div id="sider">
<img src="__PUBLIC__/images/head.jpg">
<ul>
<li><a href="__ROOT__">首页</a></li>
<li><a href="{:U('Index/liste',array('class'=>'项目'))}">项目</a></li>
<li><a href="{:U('/Index/about')}">关于</a></li>
</ul>
<p>&copy; 2013 IEHONG</p>
</div>
<div id="ad">
</div>
</div>
<div id="right">
<foreach name="list" item="vo">
<div class="item_img">
<a href="{:U('Index/pas',array('id'=>$vo['id']))}"><img src="<if condition='$vo.img eq ""'>__PUBLIC__/images/item.jpg<else/>{$vo.img}</if>"></a>
</div>
</foreach>
<div class="clear"></div>
<div id='paging'>{$show}</div>
</div>
<div class="clear"></div>
<div id="footer">
<a href="#">TOP</a><a target="_blank" href="mailto:iehong@qq.com">邮件</a><a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=630798273&site=qq&menu=yes">QQ</a><a target="_blank" href="http://t.qq.com/iehong_huang">微博</a><b>IEHONG</b>
</div>
<div id="cri">
<script src="http://v1.cnzz.com/stat.php?id=5643222&web_id=5643222" language="JavaScript"></script>
</div>
</div>
<div id='body_bg'></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>{$blog.title} | IEHONG</title>
<meta content="{$blog.tag}" name="keywords">
<meta content="{$blog.description}" name="description">
<link rel="stylesheet" type="text/css" href="__PUBLIC__/style.css" />
<script type="text/javascript" src="__PUBLIC__/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="__PUBLIC__/js/index.js"></script>
</head>
<body>
<div id="box">
<div id="left">
<div id="sider">
<img src="__PUBLIC__/images/head.jpg">
<ul>
<li><a href="__ROOT__">首页</a></li>
<li><a href="{:U('Index/liste',array('class'=>'项目'))}">项目</a></li>
<li><a href="{:U('/Index/about')}">关于</a></li>
</ul>
<p>&copy; 2013 IEHONG</p>
</div>
<div id="ad">
</div>
</div>
<div id="right">
<div class="pas_box">
<h3><b>{$blog.updatetime|date='Y/m/d',###}</b>{$blog.title}</h3>
<p class="h">
<span class='count'>{$blog.count}次浏览</span>
<if condition='$blog.class neq "项目"'>
<span>分类:<a href="{:U('Index/liste',array('class'=>$blog['class']))}">{$blog.class}</a></span>
</if>
</p>
<if condition='$blog.class neq "项目"'>
<p class="introp">文章简介:{$blog.description}</p>
</if>
{$blog.content}
</div>
</div>
<div class="clear"></div>
<div id="footer">
<a href="#">TOP</a><a target="_blank" href="mailto:iehong@qq.com">邮件</a><a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=630798273&site=qq&menu=yes">QQ</a><a target="_blank" href="http://t.qq.com/iehong_huang">微博</a><b>IEHONG</b>
</div>
<div id="cri">
<script src="http://v1.cnzz.com/stat.php?id=5643222&web_id=5643222" language="JavaScript"></script>
</div>
</div>
<div id='body_bg'></div>
<script type="text/javascript">
$.ajax({
url: '{:U('/Index/count')}',
type: 'post',
data: "id={$blog.id}",
});
</script>
</body>
</html>
create table blog_user(
username char(20) not null default '',
password char(32) not null default '',
prelogintime int(10) unsigned not null default 0
);
create table blog_blog(
id int unsigned not null primary key auto_increment,
title varchar(50) not null default '',
img char(80) not null default '',
description varchar(400) not null default '',
tag varchar(100) not null default '',
content text not null default '',
class varchar(20) not null default '',
count int unsigned not null default 0,
updatetime int unsigned not null default 0
);
create table blog_about(
content text not null default '',
description varchar(400) not null default '',
tag varchar(100) not null default ''
);
insert into blog_user set
username='iehong',
password=md5('hyh1991728'),
prelogintime=unix_timestamp(now());
�����ExifMM*bj(1cr2Շi�
�'
�'Adobe Photoshop CS5 (12.0x20100115 [20100115.m.998 2010/01/15:02:00:00 cutoff; m branch]) Windows2011:08:23 14:04:01�������fn(vVHH���� Adobe_CM��Adobed����   
        ����"��
��?

 3!1AQa"q�2���B#$R�b34r��C%�S���cs5���&D�TdE£t6�U�e���u��F'���������������Vfv��������7GWgw��������5!1AQaq"2����B#�R��3$b�r��CScs4�%���&5��D�T�dEU6te����u��F���������������Vfv��������'7GWgw������� ?�:�ҫ�A�x��<���q��I���?�[��T�㌆���<�A���5�s��7>��,x�X �x>(.g���4Ôyi � ���m~;�
?";q�v��rj[UC]\;'~\�����cyH�݈Q�}7�l��@��
�nWN����mtU����O�G�{����>�v=�a�kr:����x�)���ho�.Y6SV3�ۘ������_�x�7� ,�������������woY���݋�.����m ?�7�U��ү�92gN�Dxz���ՙm�Z��\O��_ߟh�� {���g�j�'��[{��ۀ��6[���\L� �E�e��F����c���˱��g���KG�\�����������:� H}B%��ē�^�����;��>�P���+k�3[�����R����#Zy��ZY��ۨ�<O�>�?�~D�q6���4E� ���4 �n� �7��mg��)��ٿ�1��D+l���r�8���-�C�(( ��X�L��IF��|O�rJ�6������z������jD�o�����S�7�O�VK�*�M@��ܲ����2��y(V�)c��8�D���%gݸ�ܪs8/�&��y�x�,�.-'�;� u �p1 �W�f\�V%�k����*����
�A h]�ί��#�d�SG��~�E�R�`;1����R��c�;��|���+ct��PE��u�6ed?�[i�v�~eL�R�˿׸�hѿ�sm��q6[ˏf���an�������0�e�2�P�ɂp�f}bvK:qv;�{E��i���e,#�!�#V�h��e��������t:����-~&UYK�px �Z9�j��e,�!���f��?A�����L��cG��ê�yD��)�~�<���g`5����E�a���w���,>����b�6�`����2w��߼��-k*�/��q^��<m�]�p�x]�
A�k`h� pZ�Y`�%k,!�7�]��`��6m̥U;N㯀BQ&C�]ҳ�5C�G��{?���c�~IT����e�������j?�?�O�V�`;������U|?!����,���#�c��oS)�ƑƊݦ53�T�~㦀r|U���/�v}K1�X6�V7\��޹������~&+00����{���Y�kms�[�^gP��� ;�#;���fn�͢�~���{�O�j�,�bU��
^}��f�����/4����߀���U��� �K��^�?�T��@i{�C+����?E� b��˰S���^������
.��]O���K斛��:��w��5���[S�vf۲��`֪��c�-�����+w]],6���\��R��j��/�m��L_��"�Ӓl�{{��o�V��WF�����hK��܆��k��z@gێ�����_Ժ�fMt�;������� ��y��'��� F#`��ӎ��?����L:ONk�UW����=���P��t�8�Z�r�K�H����e����
��$�(�4�=W�a�Mc�|Ƌ?�ȯҿ��Qkt��2ꌊ��p����g��j�
�eޣG?M��Wyn{'�IqD�g��x�Vm�9��aӰS64q��g�\z}&������X��+��o�֝׋ja� Úd:~���ZR��ц12:���G��ߒMg�:���*����d�������jD���+��W����`(0
����$οo�ѣ���P������^]��1�-�K��&�%i�w��u��n<T�>?�7(���
� ���}�ǭ��Y�����^��s����ڭ���׵��;�!�ȵ���ӫZ �����ɾ�[c����d}̲��ޞC�m����qCi=V��[�f ?�Q� �|���鬻6�s0X���=�5-kϽΏ��=�It=c7�c2�
�g���@�WS�~�$��= �KH��DȰ/A�Gm���>� `.w�,A�FVX���2H���F�������u�����w7����T��G�Z����B�{�� "�;`4wٻWeY��@�����_�a�����,��r�۬��v45��m���}W�l���i�=*���6�C5�~��ab]?#�����7ypHi ;�=������D�?��U��������E�z�J���)a������:=�n�38f�L X�]�n�Xߥ��.�lT~�gZ\͕>��64���.��C��igV~.�ʲ+���KL��z����|C�����,z��Ƀ!�t���!�mp(aH,Ph�h�B�e��KVF��Jΐ�� �����#\�A�Y���G��ah����z�'*��o4�s_������T���q�����b�*��z{?�U�?��!Y���&��?�zg"����Ԥ��O��_�O������,q���aU���?�[<���n?`��I���lxl�޺Kp-kt6W�{�����w�w����z�"�����nsP����u;�&� k}�$�x�X8YI����b,����f��g��Ѣ�b~յ�w��Mq�j<\���_���8~���_�E�` �Vf,uC�����ᖔ��gM�T�=���׿c5u�zv6��w��l{�����Y�}K(���>�M�GW����*込��v��xomۙ^��m��]�ja�L��Wѩ��G@��5:n�fޡD��ˎ��5���W�'klp��|\��!���*�6�վ�c}2�갱�M��V5W>�pIߘ��Au8׶v��Π;���}m�-���i.hۼ�|�m�Z����,�o�s]�k6�|�xc3�܁�P##��{������;_� �<�K1m�*�ñ�k���A�'��s�о�\��m�u�Տ����}l--5^w �����$ L�G^�9������؂;$��%K�gd_�1lq���׈�9���&�>����K��:n�#�7��� N��ؓa&ꏈ.�`�o}��E:@�u��M�cg�!����q�s�M�������I
���,c�u��`���T$��NJ���������_ׯ�����Z���Ȭ�~ʵG�"��O����4�����4̬�X�����]���x�3vۜ?���V���&lcX��5,��iU�D����[ѣ���`��V��kFַ��ᡎ!���E���/q�r�I��$v�(a!�T ���2�V��x��N���_�<g�?�̚_�kh�����X%���������/2ޱ�}Dz5 cK�k�/�ƺ?�o����W_�T�a�ac; ���x�~��Z�P�76ͻ��n�)�f8��H���|d�q�v>Ծ�}L�"�b��EuÜ��ϡ���ŧ_J��vU��ky~CŎ������b�Οs�eYx�xn!�kH�i���޲���@w[ë9٬��w�۹�-;\�������,��H���w���j=������Ե[���;n5�Yi���;>��'���Ν�*e����� �p`~�j�>��a��/c��!̓�����r2��v���%R��ն��B��u���1�U��2���o#"��f��kA<�Q����W�����ʡ� ��ȑ شzg��4��ʹ��]�7����Tp�g���g��0�x,���x��ޥ ��� ?/L���Z?�>�U<��.�Ȏ=����^����o�LV�.����P���>�h)+=?���Ek������0G�|��V7;h-��9�*�n�� �Ee��ִ��V|�� (k��*��7۸ :
gU�t�Q= ���@���I ��Y�كi l <�Mr��N�wFx%�P��vO�F��!@����l��i�j��O�u�^���R��ʴ��^M��9��3h�����~����s���s��ݷի%�Ԝw7Զ�ϩ�m�U
zk\j��ȫ'�YK�L�uk}f��]C��#E���*��[�]���Z]�-{O�Գ��g݁��"�]�a C�mc��O����eV.��D�? U,����h8�Lg�i'ii�[�5�c�a.�&!8�=��gu�W0�I����Y=�9�����*�xo������UQg��@|Yf���m�R'J��0z89��b�FS��KG���X��pm9�c; �s�l |~m���շ��x�E�:\�rH1��[Lt;�a�����3����Gue����6�{C]���ZϡcC��"TŝB���v�CYMnhp֗��Lc[CGo%K4�"o`�8$�U��9m��(�mb�uy���n;ŕ��e�o��h��͊�/��A�Pf�k+w��*�a�i�/ȋ�]3�ߐ%e$�fK�V� �0�j��M�\������@���=ۊ�����)+>��k�z/_������j�yȯp<�?�9�I�������q�u;���0I�_�̷v��#����
i��Rlt��+<��y�^�. o~��]��}#�M �~w)���0mO��������C�6ݿ怹��ұ[x��f3��h�涸��um�n�R��pZ�3S[^@��ܹ���s}7m� ��ز��$.�6G����q��WE�Y'�\��\K���Lί������������u+�h��?�q�H�&���oo��� ��;�wf��M�I��γ���S��4����O�L�,a����SkW��}}��i>��̯q�:�;��Q��O�KuwQ�Ofm`��Ч���c�7�������k��5��@�8��~�9���ܼ}�k�?W� ��]p��O�rs2���䓾�/� 4B��HxkK�m!�֏V�`���+�p�Tr_gY�ε��� �s���v�.]�\Kjq1��O�,�v'��q�"�D�e�X�?�W�9�=ƺ?����Q�9���j����I�YI�oN��c�X���?�T���8�/�^��?9��g�YvY���j��:�����SGLϸ�k�U#�����'�S���?�������Zݵ���'�+�@�IU��q�"�� �S�:��o湆�=�a3ݦ��d?NT�Kc+����0�� ��H��K�ˢ'��H���R��bv��ٛ��]w�]�Kí���?x��@=X݃�tn�X u���
�\����0�/��깠wk^�U���^�q����e�/6W��\�l�!��G�b&T��X�̵�dc��I�dA�!d��g��ߚ'P���u���7�qU�؅Ď�5%��X�L�wCu�� (]�F����yI(���
z�� ���]=��K��N^�f���jד2��Ļ�pvC]��ֽ�9����b���������b�𬑗��,�͒;����X���h�i�_s���5��=���o�+���1,��������<=�r�v��E�#crs=9��U������q.W���@�?*s�F u��ո�W��o�_9Noy������6����������%6����ܱk[������� �
+V�#�A߹7������d�iIgk��u�֚�ۉ�[���F��2Ll��[����|Ԓ�?�O��~��0���#�$���g��̗�i!��?�O���~�cv��#��,�OU��9���m6�n�E����|��Rۧ�W���Wq���k�M�����B�O�ұ�[����c�4��2�����S<A���f$�(+���`�v��]������nM~�ڬ�wЩ��w��@�;���=�+:��9 ��6��<O�{��]������yѱ��gC�^���͋�?��/���g���Y��g�j#��O���������-�P�:6h{ ���ai�C7w^>���N�����0��{[��p�L=��_�ϧ'IC��_3����迻�EZW�������!bPhotoshop 3.08BIMZ%G'�8BIM%��tΙg^~���;�8BIM:{ printOutputClrSenumClrSRGBCInteenumInteClrmMpBlbool printerNameTEXT8BIM;�printOutputOptionsCptnboolClbrboolRgsMboolCrnCboolCntCboolLblsboolNgtvboolEmlDboolIntrboolBckgObjcRGBCRd doub@o�Grn doub@o�Bl doub@o�BrdTUntF#RltBld UntF#RltRsltUntF#Pxl@R
vectorDataboolPgPsenumPgPsPgPCScl UntF#Prc@Y8BIM�HH8BIM&?�8BIM�
������8BIM 8BIM8BIM� 8BIM'
8BIM�H/fflff/ff���2Z5-8BIM�p��������������������������������������������������������������������������������������������8BIM@@8BIM8BIM9��18��nullboundsObjcRct1Top longLeftlongBtomlong�Rghtlong�slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum
ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong�Rghtlong�urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong
leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?�8BIM8BIM8BIM r����V���� Adobe_CM��Adobed����   
        ����"��
��?

 3!1AQa"q�2���B#$R�b34r��C%�S���cs5���&D�TdE£t6�U�e���u��F'���������������Vfv��������7GWgw��������5!1AQaq"2����B#�R��3$b�r��CScs4�%���&5��D�T�dEU6te����u��F���������������Vfv��������'7GWgw������� ?�:�ҫ�A�x��<���q��I���?�[��T�㌆���<�A���5�s��7>��,x�X �x>(.g���4Ôyi � ���m~;�
?";q�v��rj[UC]\;'~\�����cyH�݈Q�}7�l��@��
�nWN����mtU����O�G�{����>�v=�a�kr:����x�)���ho�.Y6SV3�ۘ������_�x�7� ,�������������woY���݋�.����m ?�7�U��ү�92gN�Dxz���ՙm�Z��\O��_ߟh�� {���g�j�'��[{��ۀ��6[���\L� �E�e��F����c���˱��g���KG�\�����������:� H}B%��ē�^�����;��>�P���+k�3[�����R����#Zy��ZY��ۨ�<O�>�?�~D�q6���4E� ���4 �n� �7��mg��)��ٿ�1��D+l���r�8���-�C�(( ��X�L��IF��|O�rJ�6������z������jD�o�����S�7�O�VK�*�M@��ܲ����2��y(V�)c��8�D���%gݸ�ܪs8/�&��y�x�,�.-'�;� u �p1 �W�f\�V%�k����*����
�A h]�ί��#�d�SG��~�E�R�`;1����R��c�;��|���+ct��PE��u�6ed?�[i�v�~eL�R�˿׸�hѿ�sm��q6[ˏf���an�������0�e�2�P�ɂp�f}bvK:qv;�{E��i���e,#�!�#V�h��e��������t:����-~&UYK�px �Z9�j��e,�!���f��?A�����L��cG��ê�yD��)�~�<���g`5����E�a���w���,>����b�6�`����2w��߼��-k*�/��q^��<m�]�p�x]�
A�k`h� pZ�Y`�%k,!�7�]��`��6m̥U;N㯀BQ&C�]ҳ�5C�G��{?���c�~IT����e�������j?�?�O�V�`;������U|?!����,���#�c��oS)�ƑƊݦ53�T�~㦀r|U���/�v}K1�X6�V7\��޹������~&+00����{���Y�kms�[�^gP��� ;�#;���fn�͢�~���{�O�j�,�bU��
^}��f�����/4����߀���U��� �K��^�?�T��@i{�C+����?E� b��˰S���^������
.��]O���K斛��:��w��5���[S�vf۲��`֪��c�-�����+w]],6���\��R��j��/�m��L_��"�Ӓl�{{��o�V��WF�����hK��܆��k��z@gێ�����_Ժ�fMt�;������� ��y��'��� F#`��ӎ��?����L:ONk�UW����=���P��t�8�Z�r�K�H����e����
��$�(�4�=W�a�Mc�|Ƌ?�ȯҿ��Qkt��2ꌊ��p����g��j�
�eޣG?M��Wyn{'�IqD�g��x�Vm�9��aӰS64q��g�\z}&������X��+��o�֝׋ja� Úd:~���ZR��ц12:���G��ߒMg�:���*����d�������jD���+��W����`(0
����$οo�ѣ���P������^]��1�-�K��&�%i�w��u��n<T�>?�7(���
� ���}�ǭ��Y�����^��s����ڭ���׵��;�!�ȵ���ӫZ �����ɾ�[c����d}̲��ޞC�m����qCi=V��[�f ?�Q� �|���鬻6�s0X���=�5-kϽΏ��=�It=c7�c2�
�g���@�WS�~�$��= �KH��DȰ/A�Gm���>� `.w�,A�FVX���2H���F�������u�����w7����T��G�Z����B�{�� "�;`4wٻWeY��@�����_�a�����,��r�۬��v45��m���}W�l���i�=*���6�C5�~��ab]?#�����7ypHi ;�=������D�?��U��������E�z�J���)a������:=�n�38f�L X�]�n�Xߥ��.�lT~�gZ\͕>��64���.��C��igV~.�ʲ+���KL��z����|C�����,z��Ƀ!�t���!�mp(aH,Ph�h�B�e��KVF��Jΐ�� �����#\�A�Y���G��ah����z�'*��o4�s_������T���q�����b�*��z{?�U�?��!Y���&��?�zg"����Ԥ��O��_�O������,q���aU���?�[<���n?`��I���lxl�޺Kp-kt6W�{�����w�w����z�"�����nsP����u;�&� k}�$�x�X8YI����b,����f��g��Ѣ�b~յ�w��Mq�j<\���_���8~���_�E�` �Vf,uC�����ᖔ��gM�T�=���׿c5u�zv6��w��l{�����Y�}K(���>�M�GW����*込��v��xomۙ^��m��]�ja�L��Wѩ��G@��5:n�fޡD��ˎ��5���W�'klp��|\��!���*�6�վ�c}2�갱�M��V5W>�pIߘ��Au8׶v��Π;���}m�-���i.hۼ�|�m�Z����,�o�s]�k6�|�xc3�܁�P##��{������;_� �<�K1m�*�ñ�k���A�'��s�о�\��m�u�Տ����}l--5^w �����$ L�G^�9������؂;$��%K�gd_�1lq���׈�9���&�>����K��:n�#�7��� N��ؓa&ꏈ.�`�o}��E:@�u��M�cg�!����q�s�M�������I
���,c�u��`���T$��NJ���������_ׯ�����Z���Ȭ�~ʵG�"��O����4�����4̬�X�����]���x�3vۜ?���V���&lcX��5,��iU�D����[ѣ���`��V��kFַ��ᡎ!���E���/q�r�I��$v�(a!�T ���2�V��x��N���_�<g�?�̚_�kh�����X%���������/2ޱ�}Dz5 cK�k�/�ƺ?�o����W_�T�a�ac; ���x�~��Z�P�76ͻ��n�)�f8��H���|d�q�v>Ծ�}L�"�b��EuÜ��ϡ���ŧ_J��vU��ky~CŎ������b�Οs�eYx�xn!�kH�i���޲���@w[ë9٬��w�۹�-;\�������,��H���w���j=������Ե[���;n5�Yi���;>��'���Ν�*e����� �p`~�j�>��a��/c��!̓�����r2��v���%R��ն��B��u���1�U��2���o#"��f��kA<�Q����W�����ʡ� ��ȑ شzg��4��ʹ��]�7����Tp�g���g��0�x,���x��ޥ ��� ?/L���Z?�>�U<��.�Ȏ=����^����o�LV�.����P���>�h)+=?���Ek������0G�|��V7;h-��9�*�n�� �Ee��ִ��V|�� (k��*��7۸ :
gU�t�Q= ���@���I ��Y�كi l <�Mr��N�wFx%�P��vO�F��!@����l��i�j��O�u�^���R��ʴ��^M��9��3h�����~����s���s��ݷի%�Ԝw7Զ�ϩ�m�U
zk\j��ȫ'�YK�L�uk}f��]C��#E���*��[�]���Z]�-{O�Գ��g݁��"�]�a C�mc��O����eV.��D�? U,����h8�Lg�i'ii�[�5�c�a.�&!8�=��gu�W0�I����Y=�9�����*�xo������UQg��@|Yf���m�R'J��0z89��b�FS��KG���X��pm9�c; �s�l |~m���շ��x�E�:\�rH1��[Lt;�a�����3����Gue����6�{C]���ZϡcC��"TŝB���v�CYMnhp֗��Lc[CGo%K4�"o`�8$�U��9m��(�mb�uy���n;ŕ��e�o��h��͊�/��A�Pf�k+w��*�a�i�/ȋ�]3�ߐ%e$�fK�V� �0�j��M�\������@���=ۊ�����)+>��k�z/_������j�yȯp<�?�9�I�������q�u;���0I�_�̷v��#����
i��Rlt��+<��y�^�. o~��]��}#�M �~w)���0mO��������C�6ݿ怹��ұ[x��f3��h�涸��um�n�R��pZ�3S[^@��ܹ���s}7m� ��ز��$.�6G����q��WE�Y'�\��\K���Lί������������u+�h��?�q�H�&���oo��� ��;�wf��M�I��γ���S��4����O�L�,a����SkW��}}��i>��̯q�:�;��Q��O�KuwQ�Ofm`��Ч���c�7�������k��5��@�8��~�9���ܼ}�k�?W� ��]p��O�rs2���䓾�/� 4B��HxkK�m!�֏V�`���+�p�Tr_gY�ε��� �s���v�.]�\Kjq1��O�,�v'��q�"�D�e�X�?�W�9�=ƺ?����Q�9���j����I�YI�oN��c�X���?�T���8�/�^��?9��g�YvY���j��:�����SGLϸ�k�U#�����'�S���?�������Zݵ���'�+�@�IU��q�"�� �S�:��o湆�=�a3ݦ��d?NT�Kc+����0�� ��H��K�ˢ'��H���R��bv��ٛ��]w�]�Kí���?x��@=X݃�tn�X u���
�\����0�/��깠wk^�U���^�q����e�/6W��\�l�!��G�b&T��X�̵�dc��I�dA�!d��g��ߚ'P���u���7�qU�؅Ď�5%��X�L�wCu�� (]�F����yI(���
z�� ���]=��K��N^�f���jד2��Ļ�pvC]��ֽ�9����b���������b�𬑗��,�͒;����X���h�i�_s���5��=���o�+���1,��������<=�r�v��E�#crs=9��U������q.W���@�?*s�F u��ո�W��o�_9Noy������6����������%6����ܱk[������� �
+V�#�A߹7������d�iIgk��u�֚�ۉ�[���F��2Ll��[����|Ԓ�?�O��~��0���#�$���g��̗�i!��?�O���~�cv��#��,�OU��9���m6�n�E����|��Rۧ�W���Wq���k�M�����B�O�ұ�[����c�4��2�����S<A���f$�(+���`�v��]������nM~�ڬ�wЩ��w��@�;���=�+:��9 ��6��<O�{��]������yѱ��gC�^���͋�?��/���g���Y��g�j#��O���������-�P�:6h{ ���ai�C7w^>���N�����0��{[��p�L=��_�ϧ'IC��_3����迻�EZW�����8BIM!UAdobe PhotoshopAdobe Photoshop CS58BIM�� http://ns.adobe.com/xap/1.0/<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134342, 2010/01/10-18:06:43 "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmp:ModifyDate="2011-08-23T14:04:01+08:00" xmp:CreatorTool="Adobe Photoshop CS5 (12.0x20100115 [20100115.m.998 2010/01/15:02:00:00 cutoff; m branch]) Windows" xmp:CreateDate="2011-08-23T05:23:47+08:00" xmp:MetadataDate="2011-08-23T14:04:01+08:00" dc:format="image/jpeg" photoshop:ColorMode="3" xmpMM:InstanceID="xmp.iid:72747FAD4DCDE0118F63A035AF6B6507" xmpMM:DocumentID="xmp.did:72747FAD4DCDE0118F63A035AF6B6507" xmpMM:OriginalDocumentID="xmp.did:72747FAD4DCDE0118F63A035AF6B6507"> <xmpMM:History> <rdf:Seq> <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:72747FAD4DCDE0118F63A035AF6B6507" stEvt:when="2011-08-23T14:04:01+08:00" stEvt:softwareAgent="Adobe Photoshop CS5 (12.0x20100115 [20100115.m.998 2010/01/15:02:00:00 cutoff; m branch]) Windows" stEvt:changed="/"/> </rdf:Seq> </xmpMM:History> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="w"?>��Adobed@������������ 
 
 u!"1A2# QBa$3Rq�b�%C���&4r
��5'�S6��DTsEF7Gc(UVW�����d�t��e�����)8f�u*9:HIJXYZghijvwxyz�������������������������������������������������������m!1"AQ2aqB�#�R�b3 �$��Cr��4%�ScD�&5T6Ed'
s��Ft����UeuV7��������)��������������(GWf8v��������gw��������HXhx��������9IYiy��������*:JZjz���������� ?ܣo`6�흎b�n,���j�c���螮����!,P� ��7��=�^dzZ�Y������nwQ5���B�Ť`�R~�u7�ۣn{��Kk ii^��
�<q€t�6m1��F��,O�M�.ě��o�7�ۑ�s�i�&����ԯ�@��̂�����s��=C����ef��a]$~�ݺ��'E]�M��e7{ � ��B (�Bm$�=i���7�S0�������H�����0Z��1:n�J�����ƽ�۷:�V����fh������z��}��<�z��pe�*�G������� UG.��Z6!�ٙWHY��?O�����f����u��v ���a��s���ޛ��9��/~h!G���~ޅLv�ۙ$Y_�h`BEƠ!�Պ�co���8m�c� ��� p�����.���Е��~Z�<����u�ĤK˱� $�^:&��o*�؃c�>�ߑ�V�7\l��ARk�Rh>��z@�ǿ�{w��>u�S�� ������gK���:�gG(��po=ǵ����� Ս���f.R��SR䀱�}��坺(d���5��f�@�� `����K�ܷ�E78��s�,��9���^��q�2���Pɔ�O��Ѿp,�(7�b�l��{��Tb��[+C�rԳ%���]M�#��<��e��ōزm�<+Po5x1� q-(#�=���7Z�s�hO�}q�S��
��#��2ƒfx~ �kByJU�-_5u������ �2�+)^6�S�ۀ>�a��Z0F+�!��Ǩ�ӣ��W�N����_��S�_�K�'�1ش ��>v��� _��}S��}닠@�䪫��+6�`Dc��z��}�A�^�^�ZxkvFRu6��p9h�F u�#���nV�"ػO}#@?ld>�*���M:?�G�]ߛ2��:snmN��553c�'��`Dؼ�5�^q��d���}�@X ��jj�x�{dzCt!x�>6�� ��d־%�_�O���a�?듉�)0#ˁZ���BL��z����Q��"��
�-��:�<_���.6��_��`��NM+_���~�É��l':�f�fQO>+����|��J���DRIR�*2�."�U�����R�9�\��soa���-%hd��Y�ҡ�o�A\�S<z4?1�Q�pE��M^"�����q�4�L�M���?P$��Y�N}K�L��M$��7��}�:r]�D���q���'&��ׇ�oߤY>q ���2�u�Vl�t�S@Ň�O�qno�5 _����?� a/?p�r����G�M���@'�N��Q����ӝ5ܬ�3ӑ:�.kv�krX/����ԟ�_r���|��)��W�B�3��� em�IyΟ-2���=N��W�'�x�IYR%ZݸI&�ږ��_Ԟ?A�Y.O0��!a��Ia�lj��2xt�;�����H�́�-4fh�>h�x�ut5��U�JjQQ:ń̤ts?��H\�:0mZ=�n=�/��b��w4����:�MD�B���H ��W��Rs�����˛��M.I�+$D���"��H���� iO$0t���|NeX~���Z��@S���;��+�Ht��a�y��MN~^c��S��^tR�(�3��������чPVb5��D&1�e�e*X�͸�}=�r���Cx�5��k�t�i�Ҵ)�u��A=t���z�f�*#�ȡ�)� ��G���/b�O�y�[��&��p�C�Ց���Tn���809�Ye�K�ܲ,���"��Z}@�k�1�:�4���e���yE��I�WIrJAY �
I�n?�� n�4>���v3m��^���_�����#����*�"�
��a���'/e<+$u=�dzqe"���t�q�chG�����@���X����%��~/�Ӓ��M��%[�I�$AL�FϮG�#�{����-��^g<�9���K�/�Y4�E8�}1"��#��������v._�3IO�0@@Tz�p�+^�۹�E��4�l���D+���m����������=��ܹ<Vj��>���2�<=��ٜk��YF{jQ�y}�:z �%HSw͖��Ss��[�ѱ�y��V%f�M(��0u1� F�����`�h��W�
S�'��"�s�3m��Pw�tnL��?�Yq-=i�|T�x����z�eD%ڽ1��Z�%&�Z0�z��b� 9��p}��$��/�o�� ��2‘״J�k��>)j�%U@�S-rfѰ-��o��;�_禵>K��gܻ�po ��˔��W��U������
 1����UQ�$���n�,��H�6�(G����O��� �U�%$�7� �]VrF�=�"�t�#ʝ�<�'��ʲ�:�X��׽���}��0W#��I��sn��B���C�TC�v�4�]ٴ1��w�M�ϻ0��\�al��'�r�)�����6��*��܍�8]�۵�/��/.]ʩMF�H��?%Rh�'V�@� s�-���ͼZB�w� T�A%[ԁR��4���w�n<7=�2T�=Ʌ�f��:w�I���ha�bkER�!����D�JD��wk�c��"ƅO#�ӹ����08�g��m��
i����OS�ֹ5n�Ӿ�S�K9Y
GM��J�G�Q��x�zY��Q�n/���t�ܧ�V���?. ԝ<z�2�%k=�&i���8����f�W�V�(( yZW�~�p]~� 't��9�t�Q��7��r�'�����ۖ�ў�A ,���q� )R2r��hm��.>��(��:S ���l�^]
�e�֥�)�f��]Z�@%���1��9a-���{'��������&� �承�������=���h<)�V����a�~].p�xP]袎!b-bH�w
�7v#�-�_�>T�E_k�;@(� M*����� �4 rK���\��^��?KOR)a1!5*���xSR���P�HH38� ���y�ml�K;h�;��i�T�a�>5�I�mRK \L�HZ� Ԛ�\�?<~#��%�#��U���"����p>����Ǽw���l$������k)?���2۴�[w�:t���Ï�������fE勥c ���d�<��o�߀����1C���\����9���AJ�1^���M��* ������)����?�D�? ����P��E�J$�xt�4�O�����{r/�zҢ�����,W�Za��er�(!p��\��=G�c����n|�k�u|���\�$,hrM0]�Ƌ^,N8�qQt[��� ,iJT�/�$�����7-.��fjb\�\����!dZ���LJx��K���=Ƽ���\�˼�"�G��q���� "E�5qcR@�B=�i��7з��D��;���&����m�25���/Q=~b�I&���,r,��[P����[���q���dy/�fb�$*��>���-m��B-��AB�E)��Z��ߐ=��~=u=^��[A��;=��?�=_ye�]��D���3)�q�g�G.g?S���QJ/������&��m��ʥ�2J�EO��Gli��B�=�,Vq0�Œj(8�9����@Y�V��uص���3��vn���˷�<��s��f!.�޵���T�m�r'�?&:lF�"D�ꀽ�ڹߙw��h�#��[J�Xɠ n��Ē���NI���.v�+8���k���tZ�4��u\]����{�#���ip���
J�0��iR����r�� ���@��N_�m�M�+X�ea�F �G
p�<3�OR�*��P����?��o���:�bB��{�nI�����Ĕ����j��v+;���Jl�2���I���'CQ_
�u������?�jQc��X���Dx��@�=;�h�Ti)� h�~�t)�1T<T�%���D�t� �fh�7 �A����6TwSF����.��D|��|��՝�/��V��N�Q]5[�>o����Zm��wN��S<XLJ��M�_��4�;�Iw$�$��ؕ�Ėg����'��1F,���v�q5M(4F�W��
���z�|u.7� >1?�d���yYHj�a OM��������o�{kٳ��-ଆi�9jSTDQ���P=�&��7�a&�@(�,��f�:>�үd�Q�鞾*!N�I"����V?�u鶗��{��ڮ_�췘��+ �\�8���*8֣�i�>�9����u����_%Q!���{�8�6�2����ZI�M����_��ӕ��&i�!%l��N<>~�]���� j����pg�)�j�q���2���z�+kFT��9��}y�ku�&����kV3��%E2A\��A�=�\s]A5����b0 qǻ�Xlkg�)!�SS�+���뭕ŚW�X�f6�#ͮ��;����
��~0�|�<GxBD�x6���L�1�AL��@)<�jz�dD5x�7���s�ş@��������$�B��`�@xTU�g�?Gv�C���A���������#f1HzfU��s��w��@�/��a�˒�~!oq���5��4��N������������+�%��*���Z�����׺n��Qi_�~:g��1ǠT��_�x����U��qQ��j<�I���_��!�_pO�W��a�� u-w.��t��L}�\>} �X��o����t����E+w���>a��Y֝�h��ؕ���?Ox;� �K5�[����Y�h�jBз�z�6�H�=����?����M:`�����MN�D$yUX�*�a���`�u�Vז֖�[��K(@�2���E��1S� ����Y$�<QB�R�*G�ri\�e��E�;+�tnm��ƍ��+7�ήߕq�����vw�n�۱�>֋���?)�Z���@p���~���G%�)8��/��y�u:G\2P��$k@����<�3�חۢ����>A��#�k�;��N��KI��f��roO���+[#Ș�FT��i��� ��W��G�{�0ns�g7�޽�W�mFI��k��Ӏ�L[}���K+D�䢕>U귷��35�`ѓ E'��N��Y���
V�5�����O!�j���,m�p��5�V�Ƨ� ����t����Z
���=�������7�z��]�J��K������hr�C93bV2��AGn��U�),�J�e�b�� �~��߶乑��6��QgA��!�@�`0� � ���u�o�h�̋)SC���`��T1�Bk@:�=����9�;�i"���m}NJ�pOOW]l�
�u�#��I<.��X%P���� 3k�69���m�U_
� #Z��oO�p����N8
�mWrl�����>�)���^%NԚ�2�UiJ���X>���is�ݿ��c��U��SϹ*sq����cy�3�YZ�(���!�eV#��r��>�ܿ-���L��
���H���
��<@�HeS�qm�tY��4a�%��P
^,Ā>}\wą�}w� ������׃�t���Qvf˙)��^��qn��)�sȴ�'���$a�QabH#m���7}��^ڮV��Z5VN�S��ҫ�T��6�5�V����������-��Zh�RPWPa��*���ԚP�g�jm�G���Ԩ�����-4�]��BVx�iX%��V��lx�$�������9cl�?u[;�f`KkSGeX��f��x׫�6��[� ܮ|8� $U+��W���tc����qRQ�"��� �H�4Ҫt�L����O���m���� {uF�-
y���}E-uqux��JY��bsRO�H�eEe4�����
S��P�X�����{}I�X�� y��pI���ޙ<@�8�ЀI 6�IR)�V�2��^u�q� 0��5A*ڪ�2<��J����S}X��G�{����D��0�BsBx�ͽ}xt���S�nY�2�W��h=8���}��>�ru�#�kcTt��~/}'�\�M��yvk�p�a$x��@8�s_>�޷�u�ƥH��<X���E�>��r��]m� ���py���~=���6}��sy!#���|3��C�Ԟ`�ƣ�h�S�
=���+d�K�+`T�3��g���zo������ߩ;�$�v�k����TW��>�.������Oq�^?*��=�!F�� ��2I+����O��J���8>�+�u�a�ij���h '��U�h���r;@��*|�3�3���5/�Љ��(CS,��Z:�B�)��q�R���e��� �5��mk'�8�&6�F�Ew��,�u��8��e���L���Erˤq@5�Eǵ14�=IJ���H�N�jLD~h5���@a���C��c��e3ڬW.� I(5 0 �y�~L��-�IIZ5
�Ѩ}Fi�l/�����~����Fc�)�� ���%�ov� \C��E����u堩�`�CK4�� ������[�X@����.��+TU$����ۣoa��gl�ҟa�b��(�O�8���5�z��%&uz���]�5TW����T���r����m��9jڔ&��,K¨�����7]���OOjCj�*Տ��R/m���v֤����,rx��/�YZ���w.⯕F�� K��E*J ������Ǵ�K ���Fs�[ ��X�}�o��C�β��6�da�#P�P���k��5ҿ����osv|�zXMz���b����{'���q����_+Y:�t�j�*^8b �*�u;� =� S���� %Ú*�,�O�QR��$x�I��R,ƀRzi��g|��ϲ��+��݁��0�=��T�]��8������4�󞚖h㩢�Ȍ% ���$�nV�ͼ����۶��� ���,��K dΙ�I6�)��f�F�GA}���n�۶�=V3��f���q�Đ��c�p2zRu��e���U�W؝��C
�ٸ%��_�FY`�[ �|KQ���6���bK���u���ű���f�_�Ojy�j�
��|�tMe�{<—�KrQ@�J��+CJ�:��S�ru��������k�j�<u-�t�Q�0٩ DREQ�i��1<?�ϸ[q�;�M�i��9�ti$5b��W5����t"�c٠a��_����ڿ�:��NJ��U�JM ]��; ���?�[N���>s��K6�j��.�f�Rg9�zq������#�i����i>(�x�֌���5W�C� �I�]���w�Yd�~���v��X� `�o�R=��oz���d�c����%+2�#Q*�8�+��o9[�o���H���(GKd�<:HG���������Uԟ-��?� �Gvzl'ml���LB��\���!}�#}������M���~�5��P�A�t�N=ィ��~��[YO
�i�ܹ���:����4 �-�]��'���J���Ż��)Y�b�|6���_@�N�>b���1e%��s'�����~څ��#-�Z�-@�Zԓ�Ǵ�'��v�}ו7�m H2���|�O�=�>��e�c�n�J0��6�'R&� �D���$ћ�����{�l���1��rRÎ�4�M���Ϥ��յ������Bj�S�|��|�3Ҫ�qPD�=�⡑!�@ G��8R(��4�O(�n�[hcyl�P���RO��N8}�C�]H�%�GĔA����������6EE��^2s���3�rO��ߋ[�"n�a�&bu ���'�>C�|��6����}��Pq��#�����iL���/ �/.������Ÿx�Ȓ�����jd�¼<�<�1�)�vE���I�ɧ�/ף I� "H^3�H؁�R��A����;���ΡݩYM~�>`����-����O��[sJ�щe��"���4�9_����,ot����;�id�+<�\x!�� c�/����Z0�=l�$m*��5#� P��5}�L�̱K �U�UO<p��Q���3�T���P�z��GUT��'� {����w�XXD\ ���� ՋSd���-r��v�\\�$�[>g���uU;��v�x|��5q������ހ�:��v���W�޿&*�d���z�l�S�����
�+2U�}H���K�\��r���p�q����b�(�UZ�v�1�AF���e���ho���i�?��k�C_���E|�mF��E�3#��X*�W[����cϼK��A����c�^R^�?�D��M˻W E(���*��T�%e�':�� )�k�C_s/$m���u0?SpCS� ���Ա�GF6�i@�Ϣӗʜ`���b�ۓqn,�&���;nS�v�޻�%��f�۴/$Q�]S�y%�G����9jj8"w�cq�] kb��u;�(����EZ�ى
�������k-��~�4|Lǂ��'� �@z:}Y�G�������=�A$y nڧa��~��TX�AY�������ِ��9�&*HF����;p��~H�x��.ol��0�P�4�����`��$M�xP ��>N��͆<�������6f�uom�C���H��1��dI*�X�zho��e+_� <)-D�l���{ ��u�K��I��AŘ�U^,�@I$�(�\�G����?�>��Ŗ�)����#�mKM�^w�������X���Ї �p��7E��7��p'܃o�V6��;��Z�.�� �G�2W+Sօ?�zL%������hi�E�ϡ � ��#�Imټ�쮒�4�h��Wb윫ӛ�zz���+cٖ����ZÐ{"rE��v���֎E��_*���|�HOUo�˕�Y�4t?>���0=1�[e��J�hTb�]{�� 2��k�M���!":����c*'���nSH�MQC ����zr@�
�E�yf�D�^�O&���V��I<l��ad[�G����YM��<7ajQ�Q�Hª����~ :2��� � X���p/������W�җ�k^�i�#O �9&�r���\n�?�D����ӊ�&��K�����p����‘�,g�9irt�Dr�=)��1�x2�;�v9�/;ϱ�-��stD7a'�'����ià�4� �[yU +O��JО}����6l��G?��P�n�۔�#��*Y�6Oum$���T�L\n�dq1k�uy�4�x��w���h�]Lwv���
i>@��PMN=YYG&��V�@\(�U B3�PӍ()����K���ןnM������zl�ܫ�� �j�9�y�j�<�lt���x�9� /�m�z�{+-�Z�nP�!5g8���#JQhlj4�Z�v�b�����I��>�� @�`M@�POQs�~���s`�E&��8����uq��~>�-‡����W�VQ_��Ƙ��}G<o͍E����g�g����gA$�}A"*�� ���T|&����䵯s�y#5�&�F1W�∊S�iO�z���%�4v!��0<�JO��|�я��xQ�sk^��p��[��$m�W�!���������e�>��}�!w,(ir���RY*PVy��U��.�`,����b�v�����%$���FH>T�Bm��f�K��%)�+�@=>}���-�ޛg���M�.��f����9}�G�V�ɱ[��5.G+���V�3�<��Y���My���bԫ(ee:�&���:�7�|%�X��A�hx��E++�:����/���j��\�U�����|� R���{�p�MY��R�H���5]L�X]UK}繎�]��?m[diR0���`M_ĉ�EjĚ�+�����������R�>�4������;'q�=˛�h��H2c(y��(W�2\����Ǹ��O޷�{���$j�/�y��}JV�x�Y��_�q�vTqvgP��Y^ʀz��Y�.����~��U�(<����G�M?���z�n�ul8��Q��tѷ���1��g��:�V��*�*��OK0i���R ��ŀJ
e�$�+�x��r�����F_�k9��J�BA ������9�z2�N� >�����`3�@�j9�Mӂ�x��{p����V� ���xq�+�ӭ<w�y�'a �����4�x�e�^�76��q��U�3��k���߅jǡ���DҾG��>~�㎪��ؽ�ڸ�7�m����WPtWŪM�K=f ))'���v f=28�A��ӽ~��V���Q$��3�?&{CΛ��r�"�r�e;��eFH�>0 "�1��$�����6�� /w[�k�5H�p<��c�ڞap2}:+��ݡ�t{�>En<V��8��.&>��ퟅۻ���1{�j��Ὺw���틯�C��n�j+���JY5y��}�}����w[���%�:Q�'��]Ė��W����
Cۇ���p��� x�����Ȗ:==����Wo��v�W�[�
Sd����ت�*ʩ�㮭��팶ء��1�~ޤ�� {�-=����_���lZ�u:��(��!G�@��z
M�|�pj��p�h���?o�Ui�K�E��[E�v�O`W��-��{�)����=�'s���n��ɨ�H� ��Jz�C%<�ѹ�ey퇷��~�Mɛz�]ۘe �x�dTy�+qV�t�9���h';�˼RkP�X��#�c#���Gv���]E��"�xm��_��?������m�*Q翅ȯ)<�rC�Ɩ$�lhޤkq�ݏn�jy�z���� DIo+
x���B�@��@�Ո��*�o}��]��v�\��.xր�WȎ��3~8-a�ۏ���a�>B;Վ���Tyt��׊
�:�uL�M&߶H����x�"�7��vbJh�i�\�]{� b�OF�-���Y�� _c&�ģ��$q����UX�lAR6�ӮM�[nx�9le�Zu���@�(�}F:�n���7�/P�ǩ��z��{��_�v��c���=w�4ۣ�>*MQ8j}�[������>QI%����.��t��UEu,c�F���y�=������Q�� ��r+BM Nx�*�9�c����R
��KGR{� �C-? R�^�C=q�[���&�?����y�x�M�����+�� >��Q^�� �N����#�H������/_���ӯiD{?�*�[�Ƶ���Pc%�i�7�x���ñr����ر��L���RG0�_z�HP�����2z��/u�p��l��]k���� ~à��>�j�\(�W�g�I��0�*�{qb>��a��n[�K�YJ�b����}��t>�d0:T
Wε���ݻ���[�x�㒟e�MǼ<��4�{[��e$��E2!��U�� ��E��5����ڎGM`���B���Q�)����D��8�v�}��X*��Y����{���+��a��Qi.�Q��y�Pn������n�.9��9�tAYoo�)ƚK�O� �@|������n�{�5_Ι���7����ܞ�Ȓ�VJ|����t�������m�b��}Ȼm�;u�p�J ���S���A��"‘���q��?ˢ�~�ͭ���Ӽ�kx�κ��ťUfCm��Xw6o7.>c��̣�=,��S5D� l �W�.�M�왶[i]� �4��S!ui�Z�t�� + �����"��ƌ��h�BiS�^�O�r��.���˱3�{��*�ol���d���h�(�6����Z����2�)U ��C�K��B�"Ǜ�&sw�[��˼���{�L���uK<��(��21�1�6��l�-/.�+��$U�L~*_����?:�|�����%%�{~(r[���E����]��w>7��t����e�<N>�[�M���(���(��^���9G۸���~+��\10���)��?Q��%��H�E�s?�{���YX��I�'�Z� 8���z= ~�f���-e'�� �ߺ�? DV(�0u�nR:��L���aO��Y�C^�N�y4���U:P�PP�t�020�8�8�PbzҢ�u<EMNI�~���Ǿ����a`ٰ�a1���ޚ����%��m��;����1�&��ώ����U ��,ԦXՊ��k��e1�����qa6�]i��=��*ꨦ����4ޝP�%��������D$}m���N�ָ_�7��-FC���6�oz�jv~}��
�*��H�SÊ��%�lm[�Bo�OS��e<����“]4�<�(?��%�|���8��;{d��[�ᱟqUI8=�ң#r�UH%��g�
p�Ԍdd���Ͼ�%���|����?xm� ��[�T'�9@"�5�q�g�{u6ۅ���X&MkS�D��e����녎������/sa��o|͌�:�Ol����w�r-�7'�`x}>�ڨ��M��t�<�_�w��x����T,�wnh�"��;�}"' ��s����.˾A��1�b�+���<}xc����ME�q�����a>��TU��^F�vg�m�� ֢�R�We�ڢ�'�6���l2�J���]b ��wc��w,���m�3&�$ +~� 4���Z�\�u���(��JWR ��֠�s{����~&�_���Q��יN�!�t��p��a��]㯧�ǹ_s��M���x��{�UV�� 2�xTp��^����?���t$|�>��?����ݫi�\m���S�f/(�*���7�~�@���Q�D�?�{z֯�?=f����&n����:O���M/�������*���r.I�?�Q%��>>����7���b��QKQ"��;����Ŗ�E���i��i$ά�EH&����ӊL��j�)�i^�'�Id�t.��c
�W�j�ˆ�r����٬����vJn/sc��>k^]���Jm� =kග�j�x�1��{���S��\|��tTbm�k���|dU;�t�++!�����Yg��#[;EMICCH�S3�ʈ� |�佶I)z��B#�K14��K�*|��]�- -��b�$�8�'�d��-%����f;7^��_�5Up��G�]��bG����r']�\��C�k�l�A|m,Q�3F��c��?�p�L�Ƥ�-�EV�U4�~ ����$r�� � �����v�"�t�~9��|�� T
�K�?���~lώ��nʢ��i�;S|n���ץ5[���6����3d��3y9�3;ð7fpL�Z��Hǒy�Xab2b�d�y�h��v�����@�8�2)�B4U�i5
���X�
�J�Ա,K3w��5��*O����|v��>ѭ�.���>�0��6���UTTl���URj]��)f(��DC������)�VX0E�\�ɛ/#�m:r�b)$�S.�$(���J$��� ���.KT�H�*�@���xZk�
Ui��!�8.��~��bM��X���'�E�;�>��|�z�8n1����QESI���\�Ȭ���"���7Fą�"Z�#�i�2, 1R8v5V� 4*k�>g��� ���y�u�f�v�D��?fnH�"���<,�VQRG�st�bv��[_����MY��+���x�j$5� -ՀI!|�����^�/���.Ce��NJر��cG��*�姪�cp�!��7�z����nU�@�o�W�^�־_=h��n�ڵ��v����2��UAQ[��G5-]E5]4���QV���{�4�|��z��QPGUgAY��}�ֽ���T�9>�� ��i��%%J�)w�JZ���fz�r{[3�Z��I!��/�������6�+we*�nU]Q�)�V�p�1��-�h��s ��]T�T�0��R~޷=[��!���uY�gJ������M2M��O"0������u�������s/A)����W��ɔ��S���d]m�НO�+nJ�ɦ�\ ?n�ݗ��a@������zuS����ҏ��� "��e~"�g�ji�\]jH��Ĝ _ArH�maʛ��}mzw X�)��#�*s���LI�A2�X%a���m�ԍ>੪��:��Ɇ
�J��ier��uL�K*� �o�܉�u�\�%�uuV�a�0���B=�yXl�����(�(I�1�t���*�'��G��/S�;�!�-�\�/�xvwq�d��1���C� �?`�߃�<��q7���if�Y��]"��Mt�g5:�u�ڶ����y����D.����DMM�cM?�����?eT*�􈑴����R� y�( 0Ԣ׿�S��m��cET�*qC$Dzd¾\=:���,��T�������FV&ZjR�|�B� F�D7��mͽ�8i-��Ej�4&�_���8AD�`>q�+��o#�z��tyeh�<���C�kQ��O��>�����J��ք��)O��ף[T/qd���a�>��������cu�UZMw�>�J������7DJ���ވ�<qϼ�� |���͢_�*�{�FD*}j�H��:r:���ժS�W TƩ�z�N��W�{�r���4g!���k۬�=Lfj/���n�
��`,S-�{+�j\)��n �$�� %$4�Ɉw\�ˑ�\O�y��҄$����fgu�CЄ;1���{���E'�mM�A3�A-�ƍJ{�@Z��I��� ��S ��: ]�事 �(��]*���Z�]�W��9RW���Ś��1$�n/U]\B��6��{� V��)NW�~�>���x�5�����-eMS� �>��X�A���A�tl��.�z]B6�DŽ��� Xj� �T����}��pu�����!V�^ � �Q�Hc���]�X)�P����#����@=Q^?Y��$��&����?� 4G��:��#������L�r�`1�{�/N�)#j
MՖ�3+5 #�J����RFJ�l%?\>���!/O/ٓ���U񽅑�l�cw�l�hk�r�k�B����S䱕���a�QWҤ�mI�1pEǽ�P��\����?��
�2��������Ր��ھb��M��vM_P���qQaN��� �W_:MS+צهl�&��]$�$y9(�*H�@���ee���)ƧP��<jq\��<�A�I�j�O���3�������=��#��2-4�~��ol|d(��Z\���x�� )�SjO��p��onF�@�;�yB��+��M:��d%*���y����H��w9X�T����#�����yQ�}~#�kR�%T"}��X�x� I)Xn
�1ԋ2�Ib,A�����X޿�$-\� �•����l���L��,
8*���� ��J������k��5�k%GU����zu�}4�YS45������=���?Ov�\nSa�[��pNAQ�CA��Ț�h{_�ʢD��g�x����W���,w��߿zq�k?;Q�{K�)M WG�6�m �GT��_��3������cǿq9��v>{����-���*"��f/� Oc�ԓ����S�[t�[��]`�Ì8�?=Rnm�W��dܶ�AjZ7�@$&5���>��7��ou���b������Bʶ�A��=u�;y$v��-#<��7坍�� \��ڤj�֤�g��>�aDZ�������
�����s���t�P�R��o�/�-�_��l'?�A��t,�bm-�'�Y:[s������w44[��wa�k��x�ܶ��<q^ˣ7Ք��2=��滛ָ�7k�H�A�K4�Y��O*�%���I��K`�I���O<�
u����l�}7`��0���p���uso���;M:�zA�HcP�����S*L���79�G�x��O�:��A"$U yae�T�4r!�P� ͭo��sV��p\"�y���j
������8� �l��#�c�P��Z܆:�:��Vh��Gi����� i6����vܶˈ�c��� ������8�5oiu��@p�j �'φ:���#�;��OA���[�+6���v�T�ۦ
��� �F��9<sJ%d��u�_((��J�P�m�nK��=�s��xY�
Z�vB8�э$u@�j��Tt0�v�� ��,�D � �i-^QR@�G�H}����nl���M�GEI�6�#i�,,1$1m������0؃(a�����$ݛ���F��[��l���=ȼJ�C-���G4)�=�f @���-�-[���"4���`~ I��^�W�=wG�� YWG�wyjZ$��:K;y��Y��#YJb�)p ��Ӱ���W6����A�����Pd7�*����^4��K�}76�UPL`i8 ����j )ָ_�7"�+>?m��F��fVN��`�&�� �+�~��S�¦�,b*i�V��� ,+J�&��]B��#�S /Lb�T)"����}(�h��tb��ma7.��[�3.+��U%Ev{;����F� �N��j�&���/����N�'��y���cɖfҵ�lb�w<"�'ˢk ���,�m�����2ƽ�?��>}X�L�&�������~���)��T����=������M���v�[f�%<'�1ؚZ���K_���c�,^0��)�S������k�L���(%ܯ��:��Ar i���jW��o|Y�O ᧯����{�sϸ{������l_��b��],k�<>�ϸ��wR�Tֿ-!T΃�̋��y�}L����v�����|�z����+���a��ec���c;�w=.����Š�W�$OlT��%�W?�}|����=-<�ʖ�XgR��ڍ����ң� �?(>�8ު��ݛ²
�I��%�ѕ����ۛ�$� -B�2�O��k�98�Z�~c���,�ᱬ�1�= S�����5���y��ٌvW����_�КW�=zz�n�m��O�=�JL�_�j��*�5����d�8I褤��T�aUQ�B\٥P�ɶ�������7/��pJ�(���s93xt����OGI�Ki(*���,#54"�Z�yTԚ�:ǕXf�Up R#�-���ԏ�́bjOo���Q�U�JS��F/�� ��(�A�X��^_|Mؘd@KC��I�}-����K�{E�����ɳ����0���ע��鵻�-+�T|�^�����N����#�G����!���ǣ6��o#Ԙ�y
*F�V�^R���D��� �av?�=�G�e� !Z�uG�z��G�������C�;�H�V�Tsͼ��F'�9?�>�^_�l�4��� ��ЇkŜk�?��$�C���������ți�G�X葝A�h)��*�og>�[-��$�n�*q�!R<�tg�R�A�ȏ��h�  A4Ni�>}����n�ǎ��[A\N]�����Q�xi�]�$��e~��R��#ԟ<~^��E�x�<�W�������_�t5�-5E:TEM5E^�EO㍛[rY�Ѫܱ��jk+;�-�m-K� UX��f��Ij��-%�^&�R
I���I�'SKE5T�i嬂�I!q"��R�$��2�y, R�M����{��ig omȶ�x�.��B2�ʤ�jEiƔ�]�R�?�� ���8�\�&��V���P�pa1����X���QOD��MD�%f�\h�ҙ$ a}7
/ϸ��v_��ۚ�rU��%�_Y
ԥIa����'�C��^�u��I���U���t�� 3V�� PW'�a�F�e2Y�T��e�Z�%�cy\���"]
؀�~}�{3ʷ|��[�7�s��%�� UN��TUc�N0�� ֆ\ɾ��gi����F)�d�X?oYf���HD��:���T�Y?�� ��KW��������i@�@ ��e��>���SL�d�B���֏�c�i ҮF���˥��H��1HWR��*I�F �<��>`�`�{Z�/\�WPt�l�̦�?�:�3�;9���[I?w&��{�
z��3 ���e&H!$źn��yj����..#u�,V����P`�*�k�V��%���s����1�jV�54�%��2z˱:���3�s]�;}u.��ZN=ژ�d����f�x�n�%���F�h�U���#JZh�O6y�i�;�}��]��-7{Kn
!X�İ� ��F)ᒊ�E�R ,�Td��e���K��tR[��F:A���$�9׍p_σ�7v{�F�������,OAT���-����q�l�W���Sn,������}�����K$N�I]!'B�39�������H�PhM
� �s��:mvۅ��'Ӑ+45��@�rz!��K�d~{���_�khlN��s�8*0{'i������Rl.W ���͉�P���$0/� ��9<��s����1K$�a<��R1��>��/o,��_�<ɨ��_��]��𞿏_����8���/�g�Wgw���u�/IJ��f��������?gQOS$�����+�w-rf��Z]l��ֵ9+N $W�*u�o3sv�����@,�m x+�Z�$ꨮq�׈��{�o�K����n����䤞|���%@��w9�ޛ]�%C�����:l�,�T �9R��v�`��e���m�%�c�!�j5�H ��h�cu�X?}[��lh^0c�z�WIe8'�s^�{�Z���ݕ��?�F����;^�-���dH2�ԕ��0grV*|���s�sK��3e1����t�6�'��JC��i�Џ�1�@�g��\��`�M�ljt��O7@Cz�>e}Mz� �7s��^��c���=�GR%3Pz)?0��"��.�ߩ��o���tusih��6��� x}�����/�Ļ|������~u�D6=���nA K��Pi��z3�1�ma�~����t��� 8�����q�~��f*�o���2�\�*����2%���K��oq�"�X��H��#���K�O�B?���[����ů�’I� �p��ν�ֿ������ۋx�§�'��?�9T�2_7� �U��>����k���~?>����nh�5֍�� ��tYz��j��:����ȧ���:��܊V-�ӳ1�~ƺ ���rM�K�Xx�]}7/�� S?4#�<�����ܹ�:`��}���|�#Z�45�D�}֌��h��Zc�w�&�N.�0p���ܑi��ql�M�����p�fj5��mT�F�vdנ���k����L�+�J���^�x�:5��SPEY\'��������)y%�J�D�BU<�so���vPA�ǼZ�q��Hd�4,�\�3H��Ub���F4������g�1��K-J�xPg-��u!����7�$�$��4��ȲܠpU�F�@�� ��J ד"�2fK�x`rdw4'^EA��SH+�TԒ]���a �2�.�c���M*qQ�趔8<`����vaS�
UI2LcveMى��m�Nع&Õv��?@�G�@�sZ|��<Ew���YP2�"��
�5�)�A�~\�9B�$mK=R�WWH �\�!}2T_���J��b�Otۤ��m��5յ��dZ��V��y+IE V�1�&��\,�7������\a|�x�꨾fn,��=�=D�Y�~>���,�}n�;����[V���۸(�u�i7���&�o٭���3-Lk��U��=)N�^������E�ص�tѱ�^����3r�|���M����9��ۥ!���ߛJ��3��}Y����d�Z�*
�zra�J�Q���|5�n����� �@z`���Ȭϸ�og�X���Cj� `&5!��s�:�VSՖ�<>wm���wV2�9��V)�7��ylf�j �>�M����w[�T��p=��+�"M� �#�~΍��W�Io:�ԩ�z�3��Iw��5�����ܱ���}�����;�%@�L-^��X��۹X� i&�*g�gM._��%�MG&=��=�x6B�������k�aBG�T�+��]�� E�2��#R�u:Pҟ�
֤|�WK��2;���_��S��\®���[{��ٱWOI<
l�S_'N���R���G�g�21L�彪�f��5k�2W� ���ro.�v���K�9�UO�Z�R����Y� E;iO>��N�c�:v]��ȯT쾱��d�۟[����R�3{�vT�2�SWE���� ���8���D�f[��zm�PfEZ�M`.�`p�)�[��N !e��ӕ�@�* �+�z/t����#�#�0�%z�kM����R�w�\ew���ٞ��� �5��\�sb������!M);��>q�!���aV��ijbJ��4#��ӓ�y�~m���|=C8)@�����:�}��1{��ݻ}�|&��b�%���:�sx�|�,u1:� ����!�$��y�":4$2
:1SLj$?gY� �O3ØdP��£��?>�~�_��2>B���=�t�$hiq�����? }B*h���n�o�7h�eȷ���5���
}�.�bԛ���kx��ʧ��=8�[E�<^ߏ�����'���ɦi����4M�\��{nԫ�@��w��ޛ����1��[��܌=���k��ϧ�»L�����:;�@{C9��->!G��é����|�S��p/����m��,X��@D�n��S��V~?vb�CN���!�#^�v��ܝ�D��"��n��<�Yq_#O������Ű�8�.�ٟ�u��ܢ�����Rc���er���7(�jV:�Z������ ޶ɷ�^卦���)���*��L���S�ζۧ8]1�J��j �?*q��Ӌٳ�A���|�ޖZ��H���6c��+�ErJrK��N��ln�]�f���bD� ���� t��q�R
�1'4�y���]�D"�
 b|�ҟ�<�H�f�
����F��(d��"P�F�Œ���b�ߓ��$K�61\Au��V����UB�*�hT14�;3��ytP�IJBa�R��I�I���H������4'�0Lr�pV�E�!����3I���K[;a�*�Li~ �cA�S�KD�<�����tᔂj������F�ȃ�5-�\~8���i=��Tԏ�#�
y��k9R��\G�x����<��v鬲R#�"�!��lU$��ߏ�>���\�;H��q�@'�%'�S���h���Ŵ�„� y��:3m�Y�]��o������7�x{����mm�Mvj��6{gQn����a� ]�ܻ3�h���0~�e5�C�I{�5l� v��� ��H�bP�����
$,EI ���4��7&�Ȇ�:�@:�x�Jҋ��Uh�S���
,�N���?���ep[�r���4s5P`je���d휍]}= Ҙ�涅+SCC] �\�d��9f�x����&�RZ�!Z�$����S��r���b]��7�2>�K ,�m5:h�=Z��関�jy�E]OKU d1�e���4�b�������{����mz�-
�R 3_���Q�_�ϋ}Y��c�z��6�+7��T�q�*��.��mL�-;Gwinj���*|��G�)��2@Y�^nV7�m��↺��2U�P��^ t�0�lw�I�}��{C"�#Fi5@+����nq�=W�S|U���V�l��,:׵�g�M�������e��I�1�mݳ*k傖HEQ5�D {{��k���6��n�W�D�B�*�U`�V׌T�3�w�;n�o%��7���B��IRڨ{�F>e�BNiSп�:����
l�����#��̥.kp�n��w5. �*)$�Xq�rP�s�{*v�-v"�J�p���"����N ԕ6�S�*���!_� F<q�ׇAݧ�{�� nޓ�O�5*��@KS�:��M��t�PVvV�b�b�񸍭�=g�v�3 ���`��c2;�}�e���H�X�:4#
PƷ���� *m�QA^ N�_^=��$=:�콖حf�M�q��Pw F�FU~@Ԏ-���' E�jhҞ*\u+9�*zxhܼ�f04Ai���J��q��$��˗��S6,{���)�hm�����b�4�]<ւ�}+�=���v`|Ū��m�q�jno�T�49�Y���u���V�E3Ƒ�S�>p�̷G�QǏ�夶�ʦhʼ[��T���9�t }���| �Ûo��SPt�����L�q)ߐ�럩�XX@��ᐦFn*���Y��Wm�&�Y�7�� �]mŁ�r ��nw�N�oC��x�]+�fj~���?�f���>����m�A�Sb�P�s���c�ڞ ��ji\���0�7-K)X���,�lx�:TdV��j(xy��E�6[G�C�O�4��\q��Ek�}��J�����#�b~'���%B��B����; BW�`e��O�IN}��ͽ����5o�[h�A]j���������� ��uQ�X�i��?������+c����21U8�ܚ�~SH�*C*��x�Ȗ�]�� ����?��0�8��p���/or4-��8�>4~dq�<�z4d��IVI�&e�H� A��{�뇒���xbp����3Lyu I&� +a�Ǥ�N<d�͒�J��"�찂1���ů�u��`)u��G=�I U�F�>\xz�q�ц��b�4$qjp�>�%T.�h�X-�)��q��Á�>�m7;u���ar�Q��p���I� T���b�g�?`��g�<V���rcs��j[؂�}}�&E9- ���a%Na�?��1�Yk)��Ĝ��f�rX�GD,��K�bU #Ksͽ��=���e���92���'�B<F�2� R�Z��iԃ�n�m-��.���փ��>�V��&�_�}D�,�RPm��|L�E�������T:%t5l��� �xa�=���s��l��G����P�cQ��5<彡#6���35̌�-�(x
f�`�uO*~-un/{Qn��Q��s)��-��4]1���y���Qk`c��m\���Լ�g�������2����O��uy��g����#���Ұ���v�J�ԑ�Š
+3��h�-�ye����Sjq�� T��+A��|�n�Y۰�7c��j�Y������n�ܻ�-���]5[>Gp�*��bz�܆��� ���w��a'I#hf&y{�7l�{,�w�`�U��Gp��(GG� ��N�8�oN�pϡݞ�݉��x 5X�1fRėF�ʑն�cnĀ����2��V�E��}G���?>���EiV5�W��zlJ�8�z�7?�x�롍E:Z�iCJ~U�O�DZ���� �I:���}/��QZϢ{��h=K�LL쫦�s��A(�������Lg�C�zE�q=���f+�8�����}���^ghg�PS�R���m}�E��EG��
Z�g։$�ʨ���Y�s��ʞ`��+�iRy�<$�Kb������'P*F0�G;��y��/�h�ԛo6{�o���6�2����Pw\�P��
��i�s�ca�f���d�YX,QD���>��r������wP���Z���~tI����}����܋6Mh�=4ϡ�x�+Ѫ�'R�H6#�f�o�?�{�:��^� NA�Y)�n����ԣܕ-�ػf�-���'c<Qk���9&r�8 �Ǽ���\׸��������S� �SϠ�1s���$�7IH��j?�à��_s�\�mV�ؓE��6J���Dp�M��K<��q�YLtd������_s9�f�ov�V�J/.Z��UE51`���bMj+����g��l/w�蓹LB}�����6ݬ��'�j�B�v��>��zM�wxn�ӽE?�M)�We�� �X�G�oW"A��s,hZ��GD�4�c����WcV�ُ�b���R��ǀ=���7b� �S8>��$w��I���x��wQ���e�����֧�[:�y1Ju-����DR(n"���X�6:�ݧ���#XYM�#�i (� ��oc���f���U� \��#$����NM�}7���5���)�����!��GDʨZE*�@Â\���Ocۍ�)�.���&`��h>����� ���$ѵ��'?�3� B��tjid��?�vV������7 ����[;�� ����%��E�� �����3�%o*���q�>}C��p� �5m�;Ɗ<���-�K���?s���WfK}�Co�'Lk�>9i���c�;�lf�����2O�>K�>�uƊ�����!�r���HQ,H����Ȼo����;F�k7-l��?W�WƤ�
�`yf�^�ྺ�ٻaa�f��~ހ���^yp�� 3�m<`�c�è�Y��|l �R�[��2�1���'�h6�b��f�t���uSN�R�4�j��hz=ٹ���r�����8�@�g� A�uO�.z�yPI�� ��x���
��&�3��u��u��c����{m�ru��m5��Dˤ����5���:�~]�K � bUWj`�Ƈ��<�z��۳�6ʩ_�ۓl�M�[<2�R��,�^V�aQ����8�۲MNj�U����sM8WGC{��3k�;���r^�y&��bS����j����KCQ���y���|���,�P�+B�zԊ�N�r#����@�6�S���Rg�HQ�a����g�s��Ny���7}�18��[x% H�m���]V��P�CL��9̛����3�ia���L�AΡ�#c��.��0"k�| ����YobE
���m�w�V��u�Ky�5$�������w|��t�=��2�Plޫ;�'L�׍W9����M,j,_�X��Z@��c�m�.���o��e����Ý.X�o��¡o۬�QLJ��W����n�$�)�C�(�����'g�z0�"*m��h <}4�#��Km��%��ѱD�����z ��η��]�P��8zZ��@�s�o��� r�0�Q�h.��7�$`�:�ŏ�QF/r-k���9?���G�����0s�ע�9��fe�n�����?��w]�W�i-Q[�O�$�dsU�}�<�dYdF?ށq&��ߦ彀G7��Z$�6PDIQQ厽o�;ȸ��}��HVdfS+��0���Q��(����/�}�__�w^���|<�f�����rn�p�4��oU׮6�r��mB+b�c *HcV7*-�߽=��{q�p�
���@�@$<(���j��G�a�[N~���Z?ݒla�#fh�T�����B*A��g�]t�x�]QP��fjv������\��*&I�D��[�����j��r���Go���B,rR��4����- Yu9@@�����ҝ�";�3�Tu�Кl.��ⱇ,���C9]R�R�WN�h�%R����I9�saNO���]��?�\E/%0AУ�9�I��_���w�@�p&��1��Z�����f_������s�M��ٻj��y��� 1��#+Y)qOUP���?�Ǟ���yۗ�5��)��ʤ�ץ��}��J��5�e:�MD����=�CI������7�L�-�R��l��M-/%c��x��]��'��Kj,.��w���Bϧ9�* �9�0��7�sZ���mA
�(���?������\��WQԥ�. 9`|��cA-u��A?���]�]�l��� Y�H�PA�4�F~�B&��qsy�А4���얿��8�e��֔M4�+�H��O�bC;xU����� rW/�խ��c�]��Y�F����%��@��ރ=�;��)�Lh +����x���f��ƧDeVD��$8���k�{�����Ym�Ţ5H׸Ҧ�I��N�Q��L�S]$��\yˤ�W.���,DiW��^5�Ă����8���o��g_
�A$�i�y�Ҁztme���$��2MO���/A5n�����=�S!�D�i��燪�����a����9wx��P�sNMIX�yVG���zۥ��(�F8�*�~@yu�vn�����)Kf�R��k*�� � +_��8�A�g2I�\r�.X���G�M$�\��������.�gK���G:@�E�������x�6��ո �Z��Cػ)$!���\& �c��L�2HE���Ok�Nzޚ��'s�ɺ� "�V�k:8���o���2l�e�'�k+qV4
+�x���
��[U�:C�w���,7�ˡ�����*�9H��SV�ͬ.�<uDn!��G��q���әy�`��d[K���kU�8i �ʠ��=��m���n��I$`CS���G'ʟ>�|�I�{�p���:<���P�w C�.J�\}}M#b�i�q�T�NQ � ~���-�{~ղ�E������"�EPC�5aJ�A�kZ��Ҙ���]��3��v�\G+�������
�
Sת�ݙ����Iv�̯�,� ���� #����{��U��~/�k���u�ņI�8��HT�(����X���j?����8�q��ň'�Ž�t��n�ޞ�D��T4Q� �����G��Yd�x����:AU�4�G�W�B���`� 5��aǶA$���� .�K�[�;�W�n夊
}���$5��fG?����a6��V��B� ,��?\���� ���պ7\�l���D���<��S�S[݋{��`�6W<=|*~U ��q<�&���PŹ�@M� MͿJ���ͭ����X���?�c���eB���AO��N�����v��E&r� �0P8���yP�����X��d�m��IǛw�z>���Q}���ӤE^��5ص�Ӳ�:�c��޵r��h�v��yޠ��\�} Y�n,҆���D�=䯱�$�M�\������-@՝�fp3��+S#^<������X���nRG��_��h��C���;���Q��k��9��.�YQ_盹� ��Z�Gm�Ј��G���&�X�S9bk���B���yT���P�x��� �Λ��c(x��C���x�A8�������o���t�E|��y� �N������j�'�=�]���Zr��v�!�F�� *֤�c����\���'�|\�$�>y�FN�����@ ����f�ۂTq�@?��K����n��j� �<CJj'��+�8��ܬ�\I�����=1frn���H>�MO<qTN��S+ȗD
��{$ojw+��O��+ �P0i¦��m�`����ܫUsR( ��^���̫��ơ���FK��M�
"��ak���p�\'���9�Fj��8~.������<5*8TR��45��AvүƇ���Z!��f�4��Yh)�7�yc����;����g]�s����b��!_���CLy��c�[^2I �H_Mʒ5��p�SI���%$Ř�k����(c=A�Lh_�b���` Ԏl拹���z��R:.���)49�Z
�O���(�tǦ� MM�&��A��/�����:SmUl������n���QE$�ep;c~����K3�l\�|�X)�Jtoor^��/`���-5ӂD�RD�)�#R �`��� N����5�G
�,kı�1� �D�al���Kzu%B��o��"��L{W5��۷fNbr
�>���{G{�qǼD�[o��=��%�(o���8a��0'�ā��>G^�=�;���XZ�C-0�u�G� >~]h;� �W��p�����\@D:V��ٖ�q��$�� qo}�����/m9
��]�ٳ�4��X��p�o���#�����b|�*�o��ӂ����9q���zM�f��D�*VI-�04�^�M��B#�f��P'�ӊ��:E�7Ez�������(�n-�?���'�d�1n�(:uP
W�I���8������G�_ϧ<���y����i�&JjzxRI'����p�A h�O<��QK�'�G^��v+yo͑ԝ�֘?��v��뽁�� ���ɴv����&��bw% �J�T��Ê��;U�q*H�u����9r�s��-�����伺���d���/ d��G
u3s��\��p���������A�M����}��l���}x��ԕV��i�����NV�g��&<G���G����<���C���.�uX]�����Ք����;/��6o! ����SM����r�)��!�F��_rU�]Okci k�b�@�gb ԓ�q��i����P�ѩfc�*��_��仺(�'�/��ڊe����S�±aq�^�ػo����rvmL'�ڢ�h�b����j$��m���˼�ɖ�It!\yj�S�F�� t��T�� ��2s翴�"�~Q�lb�������3�Ҟ�������ѵ��o�4��Q������l<Zmo�=�����ڢy>u> �xW�+�(�]��>^F#Ç�?�����r�/��c쨷.��VSE��1����ޢU�<ԋG��(��N}a�l���[�Dضuݶ��� �C�C�jF�P�T0��xk+�7�������u�IV��������v�����,FN��������6sAo�ވi�do�%��==��i��|��j��޺�ղ�N�"�\�F�}<&{U����c��:�;�&x��=e�k�ZӧE�4�N�l�?�H�Qe�uf�f�yߡ�$��C����ŭ����Cs�D��.F j��<e�Ξ�:��Q�|���_�^��颬eN� �@m�#��������6�9�A6ŸGS�$zkN�)Z�'僌��l9��\��I8�.����Џ��+ �˯Œ�N�H:sֶ�����>����Se����T #�eH��x|�L��l9�x��\jF���:r�;�V���V��Ÿ%9Q�:L9���q��wW)� � +��L�W��"m��;���|����_�96��*�@��OWI�����9+^Fm���;c��#W����n��Ƣ:w��N�L������m��NQ��#{}�m�O ���R�0`\%!B��P�A=
y2=���Q��™�kA�� ��ᡪ�=Mq��c�K��U|���1A���|���r�אT
��,���P-E�(��F�'�y�տgR�?i�M�_�l��Z�W���`�^ u���fni�������li�)�K�ǁ�4ͤ�69�5��DZ6�u�?�����iZ|��N��]qǤL��)�s�Ψ���!�sün��|�Hʕ���O��k�d��!!2sW�5ȯ�r����� |F�����F(�50��Us�����t�#���\_�<>���)�[���m���ٷ�����ޙ�<;e{ �veobS��&��,�L��b�'�n*Ha���&�I&����V���MGh�4<}1��ӡ-ǰ��?1\:X"ҡ���BW*)RN8R�z`��G�o�����{�oXd�:?�ۊ
l�
��m��N��v�6�����GP]�J�:jƮ}�B�N斛�Z+�೘�8�='O�kC�N���� ٶ_���%��֢�H�ʀXT-iRE:�;�җ�6�J9�_�Z��kK��B�D����,��{y��y=Wĺ%��иϯ�_��GS��Ʈ ?SN>���Džz�w��n���ڳg�N����q����nܠ�m�|)��I���^�-&�m.H�W�ȶ8Q���>f9��a��?�u���Zu4v6��צ�;Jb�5騅<]z�:u�F���s)ئ��v��@�S�O��,a�kC#i�(8W��� E��Q|4�1M�ۙ��5~RG6��a+j �I��?zY"�#@�=$��ĴZYe[3B���;u�2؋���{��B l�qO�jI�T1�փ�g���)�. ��o"BH�Ě.GcR�$A����!�BF�U�m8��G�6�SUR6���`���<�,l�!221�@&K)��om͖��g�m��^-,<� MI��"�++ż�n�تtM�_ƈ�1�kö�"�MO_��
����JFIFHH�� XICC_PROFILE HLinomntrRGB XYZ � 1acspMSFTIEC sRGB���-HP cprtP3desc�lwtpt�bkptrXYZgXYZ,bXYZ@dmndTpdmdd��vuedL�view�$lumi�meas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ �Q�XYZ XYZ o�8��XYZ b����XYZ $����descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view��_.��� \�XYZ L VPW�meas�sig CRT curv
#(-27;@EJOTY^chmrw|������������������������� %+28>ELRY`gnu|���������������� &/8AKT]gqz������������ !-8COZfr~���������� -;HUcq~��������� +:IXgw��������'7HYj{�������+=Oat������� 2FZn�������  % : O d y � � � � � �

'
=
T
j
� " 9 Q i � � � � � �  * C \ u � � � � � & @ Z t � � � � �.Id���� %A^z���� &Ca~����1Om����&Ed����#Cc����'Ij����4Vx���&Il����Ae����@e���� Ek���*Qw���;c���*R{���Gp���@j���>i���  A l � � �!!H!u!�!�!�"'"U"�"�"�#
#8#f#�#�#�$$M$|$�$�% %8%h%�%�%�&'&W&�&�&�''I'z'�'�( (?(q(�(�))8)k)�)�**5*h*�*�++6+i+�+�,,9,n,�,�- -A-v-�-�..L.�.�.�/$/Z/�/�/�050l0�0�11J1�1�1�2*2c2�2�3 3F33�3�4+4e4�4�55M5�5�5�676r6�6�7$7`7�7�88P8�8�99B99�9�:6:t:�:�;-;k;�;�<'<e<�<�="=a=�=�> >`>�>�?!?a?�?�@#@d@�@�A)AjA�A�B0BrB�B�C:C}C�DDGD�D�EEUE�E�F"FgF�F�G5G{G�HHKH�H�IIcI�I�J7J}J�K KSK�K�L*LrL�MMJM�M�N%NnN�OOIO�O�P'PqP�QQPQ�Q�R1R|R�SS_S�S�TBT�T�U(UuU�VV\V�V�WDW�W�X/X}X�YYiY�ZZVZ�Z�[E[�[�\5\�\�]']x]�^^l^�__a_�``W`�`�aOa�a�bIb�b�cCc�c�d@d�d�e=e�e�f=f�f�g=g�g�h?h�h�iCi�i�jHj�j�kOk�k�lWl�mm`m�nnkn�ooxo�p+p�p�q:q�q�rKr�ss]s�ttpt�u(u�u�v>v�v�wVw�xxnx�y*y�y�zFz�{{c{�|!|�|�}A}�~~b~�#��G���
�k�͂0����W�������G����r�ׇ;����i�Ή3�����d�ʋ0����c�ʍ1�����f�Ώ6����n�֑?����z��M��� �����_�ɖ4���
�u���L���$����h�՛B��������d�Ҟ@�������i�ءG���&����v��V�ǥ8�������n��R�ĩ7�������u��\�ЭD���-�������u��`�ֲK�³8���%�������y��h��Y�ѹJ�º;���.���!������
�����z���p���g���_���X���Q���K���F���Aǿ�=ȼ�:ɹ�8ʷ�6˶�5̵�5͵�6ζ�7ϸ�9к�<Ѿ�?���D���I���N���U���\���d���l���v��ۀ�܊�ݖ�ޢ�)߯�6��D���S���c���s���� ����2��F���[���p������(��@���X���r������4���P���m�������8���W���w���)��K���m����C   

��C

������ 
��X ! "1AQa�#2qBb���$35CERcr���%4SUt����
DFTd������&e����� ��O !1AQa"q��2r��BR����3Sbs����#$&T%5C���6Uc�'D��� ?�c:�UɎ��9'Y��I&;u��Y �FA���
Ol�R�Hᒉ&�U��^���"I[J)1���H8�4b�I�^�/%ԅ�Y����+���c 0ZQI�2$|��W��9z��Y�}e�Wo]=m���1��+�(��U����L��mj�S�RO���Qp�u����V���"��M�����lT-;���'��-����H�#�!h��0�1�x껇:��[��u!`��O��(�:S{qh��* m���ގ��=xB�ksrl[�~��ˢ ��R�6Jjb"J�ʧ��)IJ*S%���壔�I�CP�%]e2�*ma)RS���9`.N�[&�+�9C(�Ϩ��[*;j�HX$���M2�L�F�B�=�L-e)v;�I�|�<�����N�����RR��"�/̬ܴܺ^aah:A�����l��U^ ��U`�M�V>�9�>�B}��`V�#��]uz$�$Ǭl����O���Q�O�I��",4n̽�8��{�ρ� ���aS\m��S��q%4�aHZH�J�褐H � ����n �9�&��ž�m��3hlŃ6�k�)V�m���J\�1����y�x�����!R�J�}%����/�] ����-��d�H6�����P�+S
qmՑ�Xܒt?H�S���w�߅Kcd��_qOn༟�[�^[ Bm_j<���G�K9u�x�@���u����k��Q�w�vS��8�<QV�3��:����ꣻ�⣙�2���`��)��\>U�����i�B. )�]t7!��;�y2[II�Odg�G�D�*�ұ��|�ǪP ��Ncr��I��eT��R��pH<��(����o�iE�W}����[O�Z�pR��F�:��F�!��V�H;�C���^5��O(��ȩDhx���\���V��x��Z�gf/c��-6�IIZAI]�u�JB�2�����ІLD�� ��6��b�#^���4�}��[I?������J@,��>���@��]_�Y�b Z�Y؛���^dբ�BP����ch��@ΫWM̲�vT6��Z:>y�Z��}��ueG��I��xu�3�4��6���ѭר���Q+��w��w��5�y�cc<��}}�=��ɟ�n���>"+�O���?�Z�~�BG��D!���}�Ӂ��d�psY�r ����;�IH�:��G�~bxQ_姪����'竈��@�?~�@��} ���������#1�R���I�Ҍ^;% uҌxP{i
 >�a#��7U(�.����qS߱W�L���,_���+���ύ�]��!jw�Z]ܪc�JVRÅ��q����m�+Xl��Q��\�i��?R��޺���9Ψ��i�� R���(���A�4�@�yxC�=�~Mf�E�C�JAK�%� B��#��Ko�$e�)C�(cN��i�t� � ��q�I��x�jMz�BYU=�7}@�O2�q~��:
�kP`Z��5�t�d&�@���e�!��>>g�\���� ԢI<I��Dz��
3Jfu�Fo��#4�GIPi�8�R��"�V���$���P�>`�J=e*[j A��`�#1�lE�S��ɲ�_j����7�o������n#�&\�iq}�Km$6��I
�|�bk�2P��m�0�X�{+ $(��E�b��B9�f�[b|��XP"����k��;���˳�����-�Q
?��\#�ML�-�aJᴿ�)p_�����o�J� | }ǯ
;s�|_�\[���חCvT��m��/�I
S,��- l8JU���R )<��G,�.�@P$X�`F��A&�Dy�c����EM�p�� ���X��G~��L����ӧ߫���h�`,���3g���-즖��TuJ��3kU�� ~^��_�b��G�sv?��0�4��W�oi�{]޺�x*��P�߫ �PQMB�����➲�s�O���~�i�Jk�F?���~:=L%b]yU^F+ܱG��?��1� ��N<�@���F��Q_�3|h�6��M V;��E{�����͞\y�=�_D��4�Bs���{;���F���^��Q�Y�*K�mv���e$�5���;h�R+3i��}�k���Œs�8�sc��\���:C�!�O���|@6��?1�fam�}������ |q��uk���� {��� oi��ո�c�O.9>9Π��'�Âg��J���m�}`���I+�s �[��M�������C
<�8��0㯈
;IN�.-��x�*�j)��-��4��V��G)_����VfU.B
��{�-�NF�w@卵M-����?*��\ �U���f-m7�G�����.?��mh�+PmW�O�Y�.0�!�y�P��� ����� ?�0���%�6B6Վڀ�k#-t��:E�bIAf����Jn6M��]5�.�=�h��F#4�FiB�҅�
3Jf�(�(Q�P�>zZB�f��/�w�����Ȇ�י���4�G��i����@
rR�P~���R�;OzbUגvB�e��j*'�$bs��e�� N�Rîl��&� �"�kNӭ�8��$� ��2?�4xWD�`�>Xsܯ��u���AH?"��O���}q-l�=�����zm��2��n��8ڑ%E�9ޫ�m��('�'�B���p�A��S�hں�q�"ٕp�z8�򸞜���&\!{6M�{ � �6���1�t ���C��G��m��7ɭ�i`�]i>��s��2����>���%t{���8�,N*_�پ�=��ke'Ks�}$b�<.�`�f:ͻm[�m�.�k~ZB�M�g�iu(�Q�5��zSM��&.PT����S�9�h��E5T6�Æ����H���%n�?#��T�:�e��>YǮ���,���ٔ�n�g?g���iҒ�ȓ���T.�ű��s�`�b�h�Vs�x������o$��M{�" �������a��Qh��q0�e7���#ӑ�����`������ I�ܗ=�L��i�j�^����!����]RP� �J��� +&&��a @�s������*Ŕ�#$����AGd��؛p��-��y�qwiSm%�I�r�
��D�,��T�V�Ԑ�K����䡥�aZ�a�Z��\�=k�IE��A�JIQ�z�1�c�q��$�SIX]���H[@�3�S�pj��ہ����f�7*b�ݕʛ��=Ӄ�ĥ�#aC�Br:yk���Q��g��Wa) Mƙ ͷ\��'.¶�3�s0��!:�iB�҅�
3Jf�(�(Q�P�4�FiB�҅��X0��;H�x�~�ť��[ ���5�R�Z��T�Q�-K���]B\qD%hJ��'$z0�J��7-NC�3m.�+�
dl��l5���I0�JV�R�rm[)r]m��{G;E�"��Dd��1".���ei�R���� [����psq�;�h�
Ygb|�z��;��mj���c\���]�Q&�i� �](��f�q����l.V؜~�V�1�}�@�3����+�Nٹ!�S�! ��~��t����h����yˏ����"��ߌ���_�����O���8��.7���F���zG;*A�!�����F<a��w�"�s����M��}����w�i%AĬO"���]��st��Κ�:�eݑQ�ϩ+�+A�&{�)�Gk-���r��>c8�jC/Ҵ�l!$�l�/s���7�rg�s�./内ԣk'+�m���y��� 5���F�Z%��H�8�)�$� ��+���W>q�t?� �b�e����ʍ�~��Jt�8$tg�����ˍO"c� Hf�Z�J��FK� &D+��y V�sڨ�Y��,�d�_���ҿ%�h{!0ܼ��sB�J��#�5���,�5�h/H+U ��X�'��u���m���^���U�H�[��.;j�L�t[*�-�����pM�9'4�nRm~#q���R�u�۩�RIp ؏�xF��P��q�)pP�KͶ���=R�O��6��P@U�9{�m��t}5�k�
3Jft�FiB�҅�
3Jf�(�(Q���*h��|%'k�g�B����K�q<N�u"m���c�()�Z�j����}�s'����:A%�����6�����ǣtw*�G���L�*�M����֞����z�
��+GT�:�!��s��!JV�T� R�S� ��9W��\�a%�($+g2H��w��fB��X�)��iXRT��y �x�Bu��s�N<�=�ް�����C�mw �[���f��J����זO.;��s������0\�vtVͶo�����>���5K�>궾n���y�i:a�~B4�q']Ė�)�psr�+��q�O�]m�>�s~po�0>o��8�zhȃ��N,'�'$z�/)۳N v�ֳDf���(�خ|5j�OZ����"�tV�S�� �I� �
dCx�H��Z�����u�55�q~��1;�TDy�zs�|��Ob�6c�[���BsM�d� g�_�_��JH���LzBS==a�[�\?iO1�_���YB`���~M�.��j|ih�&�O��ҕ$�W�.{�
Ԡ� $�����˕M�=��+���3J���i�׳k�M�NR��)S�n%E�u�&�+�m�cmnP�!��Z�maJm\� 9�8������ �ܤ��,�f��3�@:��\�8#�zk+IA��_�))� {=r.�oz�nMM��yz�SHZ@0O�O��oD��l�vI=��z�Vȓ�lbUz_V6���Wqoz-� ��]�3 <�̎�I��YI��:�f��%%G� 3�hl]D�)}���!a-��ؕ��cZt�55�SH����mN�T�[�ZA���~��NA�\�8\���'Rҟ��q+�^}��a?y��F����:�[�sk��2��i����{T�q���h���9
? ��t����{S���#����~���Xd�2xd���Kn�-i��0��+�Ϙ�&�u�{�}Ѕ}���� ��w­H��{i��b2�<Y`�~�A?զ�����"�-�;�#�$G�k�Df<"gv�px����']8��'�T[R�U�F�)��r�, 픯���(�S��v︉V�oݷqp�Y�xv�� n� �"��n<�u6�\,�6���4���}F��4Y��m���S`��&��`f ��!�I�O����"�xI�{P*��.����6��G�:<�ܔ�M�g�x���0G�0��h���Q�� ޯ ��P�)=0ps�h������5>�I�>�$<��-���O�S >� ���������P�����m<7{�{P8�w`l3�;oZ�.�j.�a̹G��)\�}wĆ��u�*ro�|Tf=*a?�6rICwp�^7�_Cg��=�����<LD;�7co0�a#��^���������3(��,O��0O�I!4i����L:)@�N��j&;�� g(�;����� �v#:�5&�Q����L�ϛP����G�s�&��hNb� �I|ά�I3��๤!Ēv2
I>�� U�������[J�̥@z�y7e�y*?6eeAUyd��`�z��L�礄�Wu�~r~����|�v̯�W�W�<���x�V��E��t4�N��p�h(�^�9�3��w�Y�����e/B��0k�:Zb^vt��&�F�#z��
�+���.$ۮK��*qV;Mi��T@x) T�� Q)BI�SI�"��e�ԅ!I��+�x�#e��Ru
1�+�jur/(K����F�x���[P��hD4c�=��[��Y� M"r�e1�b#FF�(�[G��MC Um���jڹ��``�ohX �1��܉6o�76�%.�&?*BV��rC���JBs�D�X��&s�6Ő��ܐ3����D�U��E�g{z�-m��q91L{hL��� K�[]�XP蠥,�<���.����׳nZ܀���O�����Q������w�p,��Z�B��u2lz�f\�M0��Z�H��AJ��u�����r�Ebv�*�\%E;W $�·��x���«+a��������&�\�.�][��$�>���>�NN]x�^h�+++"�nY��<G��)K7Q���i���6 �8n:j>��rO� {��[�7�]�� �����KƢ�z{�Q{?4�F�b�G�l����+y�!E+I����0Ak�רe�=S�zֆ�\� �e%�vV�J@�Q�f�����>��\���4�
Uj��V�+1
3��Tm���%M5�m��>��8��F������.eG���FO�s�kk�c��e-��DS���!��/��0��:��!�l���Х����#(��M�sz{=�m� r�a&]jS�N)�ǵAw$���iNO\�uM:N�'��֠Y��]�k���| N����mJ9�V=��f-��}��]����i
[jZ9�d�(��I����bQ�*��w�
���C��閞-,d����Op��ۋ��f�r��י�r?�Oݩ�X%R��%}�O|:��3aW�K{U�#-n0��x����e��A����T� �K�{<����4�:r/�0>>��iE*��!�z�:(�Y>���cH���.�&�[�~`���
v7[ջsgojm�B�O���Zv5B�:ۍ�B�!`���zA�5���i�̪�P#��A����� �кH�̪��̍��4��В�e��'�kF��`��u��;���� ��;ݾ��Aګ�۷#Ӫ�G�;;�y<��c���<��F�����==.�hٰQM� n�;��A_�l�L6�B��R|�H�F ���.#�������[�9�+�#%(qI��<��XBˮ܀uN�ш��Lx����j�J+q#�A#a�@��tv�t/k�ܷZ�e[MT)MŎ�m�T��
p��� ��7_��J���qe3��7[L��}�M��J�Ui5�[l*]���*ĝ�n�2�냵}�h�G��6��áؒ�)��<�eĽ��Ǽ�G##Si�h����i�Rt9��pPٱ�@j})Vk�D�+Or�B��D4�-���õV�zS�"�
��� � ��f: ��ѧ�(������Jq��R�IIփ-�6rV��*!'Rn�:\fa����)��%Jڵ�a���T?Z�5��Aӵ�~��QbPg�����’���*P�0y_q�>���+ce>�B����Ua� uكO��̃�Y����_� �K��H����%>���P<Y�KB
W�Cj���*�����]����@ S�(���&)���b��R���)���yM��r�KL!խռ����A!������Wʕ %�Y�F[ J}�8N͗�veZ�D��P�l��l_U:%��+���n�������a%1�
����#�D��R����0̹�T/xe��il��G���¢P�r��qE�1M��
mC��k�a��&�G�J��/ ��\���mz rKS�JZ�r�d�Z�B�BA�v���9�tq�0���o��q�r��ZCu�¼�Ni�)�Y[��RFJZi��=p03Ԍ�ܨ'X�� M|��m�;>|�5Y�f��*Է���ω�
�[Br�����8*�Ӭ�����`�`��WU�um�㾨��ժƟ�Ғ��#8��_�<��(9)*)$����TE�y�r�O�5Xw�6���t濫��=���[_��U$��<Y�:’ n�J��K�.ٴ�6�D���U6�8Ŷ���ݺ���������9\�m�F͹�B^Z3 }��ʻ_�j�����+y�Z�W�EZqA#>�iRP���5[:{����Q�,��{ ��,y�}gb`�����O�+V�����\ql��ɹh�qc�Lf��Y@��m\���P�����S�Yl]����J)*I<�����_q�M@ޤ_�m����.�xUhDbԞi9� ,��ԖQ�H�m�)��u��!|@��n� Sf�s��``"�vA}��k2���R_A�Z�\�P�AJyP���;<�^�;-��$X�@��#t0ԫ?̸�Pȓ���8�;�!��/�#���=F�|‹&mA/�j*}����2�.99R@��KWR^�2�ҵ�ҍ����&�NZq��g8���Y9G��2��*mԏ�A�ٺ�z����� ��6?l��� ��]>��l7oλ�O�0���q1զ������:��<?ڛ�tC��]� 2؂�%�/�i�� a#̝�%5�=vbI�JU�:�5���������7 i{��|ׯ�����c�ȍI����`'�{<����v^��I�2k�>Њ�Ѡ�5�<�� ����]W$ ��z�0�Q�F����ďLw�W�0p� �p�����_���CF��LN�hֿd?�����:��8��#>�dg�#D ns�҂�M��-��p8[��@�=��Q��sr.2�Z��L�B��y�[�����a(@Jz j"��}�L)%m���*��{'g#cl���nba*�Lѐ�hPB���m��\\\_-8 v�����Kcb� �bl�6��?' 0�?";jW_.�S��i)��zvޱ���(��" �f�^ԒI��z������-��{{�Y�Ҙ�[�U�)�h'��.-��z�s���Xf�&�e�h��Z�pV��(�^h�a��a#�F�W�7��kw�Ǹ���OE"�5�D��V�jHQ'�R��J�T�q�w&�Lmp9�M��tZ��Xj��\ ��DD�MIDY�wo�������i�EᨋA���8��E���Q�}I#�~�?0�c��<���x�D�n������k�U{�t.9*]�dD��jRT�ʖ��Ng$�Tz$�ytX���WIqܻ��)��Gs��ۉ]ζT�#T�P�TJ�b�j[�K���R�8�m6����.:��AR��f��td��$GɊ�6�ms�W6���N�EF��ʗLR�T��Q��_+o<�S)��v��B5��_׌g���!��"lg��>��n+�iP��������h�IB�P���B�FB��A�iB~$g�[ y���.� ��s1yI@R ����� ��D�( y�AǺn�\�]͝���yh ?U�hR���V�g#�TҝN=
��b�3x��9MV�!I�I�P�&�`���8%���˴��;s��=W �C�.�Bu.ܶ�!����<»�⹟A�GtIlC����ò� W�(�T.;�i�'��7���}���y�����+u�&���6��F�U�#F/>���G�I�q�[q��Bڴ'�ҧ䶩� XR�����߁Ȉ���1Jm�f4k��>誮?7���H���j��U��PfP]���B>�j��e#�Z|Մ+�Z5a�Z�������HP&�T� G�����SS!�{�^�ų��t>�z,&{�̭�S�J?�M+*Q�� z�|ߤy+~��3�!�����#�`�2��JM>T�͏�q��_vR�����tvPO���h���X� �cY{;�e��]���թ4P���m����9����s�<S\�33iSm��\(��D�}�b����h8z^MIq����~�=׍�S�b��+� ����ET�C�a���D�@��1P�l��P���Y��yާ��8�oh���G�'���s,u�?N��W���6~�ў�Pm�Sσ��H�� {!�M���;�h���p\1��G�u���P^p�OD��-CqUw�P^f� d��+<��GS�'�J����/S�džՒH��7�#A��
�����&�:MC���rsʐ�z�ո\QRh�Q#��q'H�a��acc�����D~c tf���UI$]9��Sq�������U&��:MZ�U�[bꞧ�2(R�ta�$�u
���z�[�s9&�B�m6=�e��yp�����S蕟+mh�J{ �1��H�{Wf�1��3����Ԝbn������E�%�1��U�O�x�-���;dD��ϗpQm�ׇV�R�A�Sᥴ�!>������&�\^.qU pӎ�PS�I�*fs6ߗ(�T(T`�t�u��
�5ml�lCk�B����U�ɭ�.­DEb���IDPU �+ޡ�-Y�
�=�KL��.бajB���D��o���5![m������M�m�m�� |s�|럳o�m�e��"�\jRRs�˜�M��w�?-G0� 1ҝvd�:�?�$�a�n`�6�c�/?��1؍߶6#����1!1D��{o}$!I��1�V3��*�a'FYgo�"2�v�"-m�IJؿ��*�\D�d ��6P\Y�B��.g%,cR ����A�ṱ��6�ڍ~[��З9��o8A�h)ϸ�Mn(L��H�@-0N�I����Bm�*U�i�393"K�{���J�C��$�
K��$���F���IVɼ.�[�=��n����q�T˭�ۻa�*5M���":)�-�!ļYʔr<v��^q鴓�<6����&�il��2�UI2.Z���H}߫Syr\�4��CKy �i�[�ū��l�G�p3�:�i���c4m i�~�@� �@� b=�{�l,�W\������aG�����z��:£)0���T �嫷:��fB[���>�JHK�<�R��� �#��I�kTm�÷/�R�0'{K��e��㯕!�V���R1�G�Y[�C�:6@Lvܝìn���nVYZ�����2eHqL��‰>�:������+�hFHq�8�A@<xs�N�cr�{h�>
?u�sk�X�l�ﱕY,�·]��G(C60H#$�;��=T��XEH���.�)���*7�;lߺ$T E�]5��ZHZA9�G �;H��Ո�պ�C��R�%�����L��I$ܤ���}ʴ򅂭�#t�/k,�;����ҷۓ)O7��%KJ��ώ���v��|��[(J�`l��r';we���6����\�߉+�ڑ�6%Q�
�qEBQӼ������㜮���u,�BJ��/�vIP��d��qZ��?��m�hֵ����o��]��ޢʨW$?�m���#�`�`�Q�Z�L�vi�y:|ëh�B�M���Q9�D�=M5*���� !�Ӛ�p-{Y _�}#ڛ%He<l��z⒄6�l�eD�r=H���F�'?����GRz>�(X���u����ݫ�l��&к7�o�V#-��*MFL) -<�8q�#�z��kމ�r+ %�M| �6��������ʵѢ�暑Pd� �m ���
;=�)���W�g�� � ���w��tt?�2߿�L ��
���?�Y_�^����
߲��"!8��n�J�F �%1���q��m�B�i�R?j|�l"-����a� #�ݩ�&�ه{�ö� �0����U����1���üR4������� \��O�1���K�N�sdw�ā�1��m.��l� �B�f��E~:�����WPB��0}0G��}�Y�;30w\yE`��lۼ.��1-�%e��4�)#~d𵀀�[}���Ri� Ȧ���'�ۭ)D&J���@8N��D�̽=�y鉴���_����&��CG �H���6S�/f���uip�$�ʧ��>�Rzk�8��A�~�v�nwu*eN�ܛr��$4Ĥ���[�.t㑆�XK���‚��zk��_(ٿ��.������x����V��Aي�y��Ԓ�{i>�D��>�5��7F� VW���b��)�F��u�3���]¢����F��}��3�ᔥ�6�%䜩���ܐ���:_)9�G�������g�qM��fحc8_5C����|���� ���;ƕ���V����#�d����^���09ݮҽ�� ���[�D��DljJ�p�I>%}iY*=I��ϾxF�]��`arqm\m�f��)s���F)ȎԾ_ �Zm%��Z����̾� ��JFb5q��֓dr'��-���*�N�5�8�������uըW)�V|����|u�l3�������g wF�� ݾ{����%(z}�Nj
��u�r��IRޡ a)%HY��3�@ѫ���a(��nB P"�m���c�]�� �L��$�E�To�n � /bt�Zu^นC��t�dP�rg��' ��IުO�H+6嗔F�ȴ�矜v�1�77 Fm�mť�wh ρ�<y�sPQ_HRd��r��r)J0 �N_ޣ�` ��Y�H=q�S{��C�9�#���!nԿZޠ�l�U�y��1�W�� �L葳[�����S�����#���Ox�w�=d�2n�J���8�/���Sk�_ډ�H��V;���ׂ~����jںo��S)�}��f̉��|�-)���ILX�Ч���K̡k;6ܛ(^�D���(a�U�j䌅�y����C�WJTm��mڔ����RK� �� �K-�0�e�I�E�S�����!��2ℛ�*V��<��g��ll��Q. ��B�Z�ڏI�"(J��(o�S�:|uĘ��5Y�8����%DTXfyD� a���۲�J�l�=c��g���~&��b.o�@���� ��o���!�?�9��p�pke�S�<�v�X/Ǖ�>�h�h�)�E%�O)��$��1|�U�`���m����]���|�Ճ%_�`�>Pd����Ta=��x˜2�KjZ^(���+z�� ԩ�Ʃ��^�?$Uֵ~��Ge���2��̜�B������[�A?F�&����w��5:�A��:���Y7��n��l� �]��o+���W��+��^���4�ĦX��s��<ά���Gՙʆ�y��@��*#>v�bD72ʺԂv��oτ���^�6�n.�l�ҧ<b���*܎�N�,��BR\VHGNFNH}-1?2��<�����ن��l����HC/�����-���/e,��.�M�\�6�Ji���S��7%ư�a��6�
�9���*�?Q�vRM�� ���eG�PٔFz $q9�xӵ�S���*��7֥�N��ąz��:��4��bcEj�Oq)BJ��2����In��n�#,��'r�� �Fc�F���؛ V�(v\!_���M����;��< N���C��[��]����SZ�I�:�;��wN�����\Ime�R
�AlD��U�6D�A+N�'i
�`G4�'��'2�*+��d��T�+�K�߻��a!\�ï�ܒ�2�����(pV��3��{`vpMej����Iu���� ^`�B=�$�g�_�vxɥV.ϠŰ�T)�s�&�����T�w �rRV;�
[�!�ԀK�嚝�̐ķb�����W�*�N���6�O�\m��i��I�p�睵�𽇨ۋ ʿ�v�V�zIr=��V�y�@m����Nt�J*��֓��o�$�(�$�y�u�"SƸb�2Ym�|�~ 6H�rxćex���io���N�����q��ʡ&d�:�m>��̴V9y�t�����k��I��/d��;�"2��&,��
��m.��y���iu��p/q[4��m�ZũR*�ۙJ�S(�f[ C�Xo�H�� ��5T��QJ�A�;R�� -��c�!#��.�l��Z��\�����lؑ$�~�d%��\��G��⃟q�3�z�A-��2�V\���R>&8'T���]�';7���ͩ�-^��tQK�*�s����ӫi�G}��P��>��%�@JP%`!Bq��+sҲ�Q�fX�r
RQ���l
�9�[}�IAďP$֙�eh)U�Rn��� H�d���u⸭N��ط ���ʜ�����j �d�����P5�9���S+bba(ZNiU�CD���˥�yu-dSbqo;��+�o�mu����*%q}�P�œJs�#'�L�~��k+2�����U��`O�Ja��0ḻ�_X�Bm�g=`48<�9?]#���Ի��o��)�)�?�/�����/{�q�ղ�����ٕsU�1��9 ku���9�$�H������� qH)$�{D��@�?����.��%[Bقmk��O�Q�U��t%(�ʖ�OI$��R�qV-( �f�G�E¸�:�e��Ͼ ]�\7o��qIZ�l=��U��`!��!���!���C����d0�l��!
]�9�r�N9��g�#�K˭h)F`e��6�
��0U�E�ϒm�^㧊�u����rP�3�m���)uI�=�j���\(��K�R��+x�VI�}�[�ZD�AJ�wm�}���x7��uC���&���.D&��Ե�|g!#�ݨH~�Df]RM���7�׾]�J�rba3�턄� -r��� �Rq硝����A�N��-��pY�5�c�
a.wѻ����@㛐 ��D�d$�� 3)� ���PRlr�����o�2�V���7IJ�3� ��nbao �~���9Z�^i�!�;�g4V֦q��;���g�Ց�R��祷��n���ي�Q_Y&��|�������CR��#�����UFߢ����İ��3�nh��\k�:��~1�(��Oq�t-����q;d���{�k���P����)��I��CML���C�-HRT� ��A^����m&�e9�8�c
4�½-*%�.G�!v��"�~�����v�^�}"cw$)��O�"�`�b�P�W\�1�tц�)/=Bm�'#n�;�i�W�����@�Ȁ4�`�����i�}ݨl��L�F��/��J*�\�^���v�CiX�s��mI�*��0A#]u4�� ��m�_-/|�t������&��kg8�KK��?� �l��rN�I�+S��Z��M�!]�i���#��+�I*-�������`m�_�R�(l�Tsׅ̈́J4�јJ�J��0���G�:P�-�fpGS�]���u�Qv�nk�>�n=����Y�R� ������iũ��Qmم`u�&9j�d6l���`v|!w�-����r&�p�jXҠL�)�'�q�)q�-4���H wa:�R�\�Nsr�Q1)m��������Rm�Ӓ�w�Q*�V��H�l�R�ߌM��9ј~5�.
Ej$��C�K�:��Һ-��QTs�Ur�B��N.K^�ڎ�V�g�H8�������vM�eɰ�w�6�*�8�ۧUEF�-k\JS���6�P�"B��FJ�<�'AJ��Tݑ���\��ag�]�7H������jp6o}�J Y�gLm�S��m��
<D�����Mp�=I:��ɤ�:P�S�.��d��g����OM�)9������$�*�^��������G��bFP? &!)��y���#'V5�����O�x� ����k\�#�j<0��W�鶵�ܛutˢ�p�!Q� R@�}�e��a衬W��K�UB?Z}� �vc�EhX����:�{��:�^�NG�^pR�~���+656���bDs�F�%Cy���+e�e�y��r�����-�p�j��ln�v\I�Zd�}�Lj�C}4*~�Zq=D�"�i
�=sN[�� 1�����}�m���V�<R�#[ ��le�}�~1�w�.&.�����qw�M����^�����K��1�쟣W�8�yJHF=�E��Z�5\�K���Ғ6�@�}�>1'�b���A����J���̋[����N/��E���$��M!iX�RV�G���+�
��/���p��x�)Ă���SǺ,ا�d �U�,6��1�����a�i���]L��I?�^����·�숧Si�累�a��d�q^���A�c���o/)�/�0T�57܏5C���}�� �.Ӷ�͆�a9�lt#��.�іU�?f~�`aҟ���'�Q+��g�~�l;�b;��YL��
�$4n ZZ;��]WD�Šr�Y*�VT,�>u5u�2
q|WԶm�Z�a�*�_��7CQ��I����޼�9tK��d;H��TV��Z�\W���'���BU� J�H�a��B~Wki��i�T���R�# ��U�mB� gȈ>S�T`Lf�K.!�Υ�]B �ZNA�! Sk
I�gC͔(\c���Ện>wB�p�ۥ7i���K��YٱXr� !� ��҉�J�L�nC8����E�L2��]Z��9������ K���e'/Qc+��;��>;9�7�m։���� r.{QJ����"<hi�R��7���K���V�⻶Jʒ�l(vU���'�Jv��u� �-,��D�+qY\��8��W�2�*����fI[��*9��`|�/u�<�V����"V] �D�=��ל{�iB�f�]t�V�k�2�mI�¨�Cam��<i=
s�@�)$w�&D��*�NG��LA ��j��u'�<7x�޽�U�\9—T*M��.�l�ÕsEh��f�*,���t��<��9�H�RST% �, ���|�=���sࢂM����Sï�����huMϨ�>��-%"EO�tƅl�V�T��)�Hu)P�V�E�0�}#������
�H��n���v��w���1�l*K�JՒ��J�������Āz���>�������!=6�p�w�+����\��*q9��e SyZ@�[����t�7�t��y��7�6�ʹ��G�)|�",ӏL�l_2��ȑ�l��c[�[m�W��6j=��dm�G����Â}a�9���N2�U�RF]vF��J�S�3�Iӟ(ume&�;(�\�V�c�NB�*��̇#e!@M���~��/~vv�� �[]z�hu)�Q��p�)u%��M�N����Pm3 ��/ޑc�ҷЦ�t�¸z��(�x(B�� ��?S�w�ʨͼ��z� Ȏ���h�u���RG�F�7�^ī ��Ӥ_ab�ke ��( bN��6Iu��i��(|G8M���ݥV�m���Z�y���*��
��e5#%PE��P�����Y��{�mDqO ���R��mv��9 �F$�j�!AQ&�
J���WC��#�(� �'�5i�֔m���^��x�#���*��I7R[[!@��U{X���C�1�0���eAhT�
�d(w���׃����cݡwG�"� g���媨"Փ�{����J���' �f=:E�=N>��t���)ED㛧Ru2o�f�Q;��W:<��,��nI>����7���l� �����l�]�/ڝ���D�ʕ1�|���7V�b��e^PR�d�������z�zq���f�̫$�q<�Ghw X�Ԯ�Nn���$�(����F#U�Cs d8����B�>��YJe.�!�$4
�s�(����X2�����S��'>���SD���@���i7w�5��v���O� �j�A��_��U�}}��W0A (��$�!@�i$(t�/�6*�p-��(M��y|xi{�l,�-ը�)W��^�������7ox����m�P��[��Oe��ݥ��e}.S�>[{>���TP�C��GC��VR83�by��un����Ov�c��X�.��W�b'�7���\^�Hp��U��F�vݗt� EoT*���҂�����m�1�Գ�Q���,ޫ$ۊ��Q���m��jT4^�e�sAm^�N�V�s(+N;֋�P�lj?hc��*Zd���Ge􀴅`�Ol6��Q]����E�=
4U���*i $t ��R��X�C,��$��o5��҅�
0A��(Q �����V���퐵�9ŕ�k4�0�NJ���9'�>g^ə�@�VG��7)���m$��=ԍ���v�־�4�1�5m�"�Le�d�F� ��ε��+�@$@�ꖽ����nܫL�հ6��#KzD�ݫ��ۂ��;9�%1�� ��W�q,�K) �u
Q �C$t:�q�6�,d�KfN�aH�@�J�x3<2���yY�aQ6�pj6��qN���fŠܕ* '�ϙ;��I��O���PV�h�BT��% IZ�N�j�4����Ar��d�n�J$��R.A�;�tz]2����BU�U�X*��4��6����۽��]2��"+ԕGi��� '����:���n�ߥ�X���m�ss��T,GE���r ����6 ���v5�1��*٦�nc��s�؛�QM�;����wd+�z�B�j���U�kZ��GqA��A-�^׽�
���\�5�z�j@�s[pI+��:(KMt�&n��OԷ�ցd̷Fb�2�}{��x��g]���@�8u�i��T�L�dK�!p
���o8#ƕ���C�J�uRu�t�PlT��W��W��5O�=I�H�r�0� ����X�
�����]Q�-��7�P��H-Iq�D���1��WL�('��"5[�8�YM���#+��VKĞ@��6-��!s����Ĕ�Nh<.� <�w��…�Mk�߯����W6��$��TFO#�<�#ܴt#���-[��UJ}H!*E�XU��9���`�I�[ UeRWl�k��Ȏc���t&��vJq���^'��õ����~�b_lDw�&�������}Xͨ�;&����{)#�zw�i�7�|D}�yAߣ������@��cP���]�s?����#6��[j}�XP>�}2�f�7NyI�8�"='�.��J�(?C����cqw��'x�J���祕A�X�J�R�0�T���a���v�\RT�TW�twD�\�[y7|E��V�Ai!㴤�o�#m3�6e�n�4�V-��;�E��Je�I}dr�;�}�*����9RT�c�w�Sn%��:y�r�����P��צ��W�IT�� ����<��T�/)(R]J�R�9�AO\��Ck���u9��W���}��G�h+�s��j�v��s�-��em��խj�TU��R: ֯�����@,s���q3ׄm�U�y�JC��ݕޚ���g@��(�[nD�Z}�PՑ͔2�n'�G��:t8��l_�s�/0ls#���h�{�6���̀�w&�#pn� Rީ��;tx���g�^k��4�9W�âu�����k
(RA�ӑ�Å ��J2H��n,3����"�+���~d�3I��:�� ��߳O�zW��s>ڼ�ٌ�w�Յ�E�{Z�t�oEl�#���9�3��=!'8�n����������Q#?��=���b$�_�B��xy~�|⾄l룆�Pً0��p�c���?X�1_�������'��e��5M�l���-%+B�!C�A�Gߨ�7���E��E�z��|PV��4x��‰!����1T��
R�>��u�F0z���t����"u]r.�v�; �����{�EiǸb�1����$�6���w�h�pڇ���[���x�(묋�F7�լ�CrY��t=>�Hv<F�p!*qX�*=��҉4ĕ]��rJ 6�B�үO�ߗd]JI;fa8OL�ͧ��L�n�?�Xo�����O�'�i�B���hvq�2��i��}M3!.��j'�==<�1ŕ9:�`�K*��H�ٍr0R����=��@
�Qȃ�0QJ@���$��58lݭ쾨�ݽ�F�Q�-�!�����苃q*�"�SK �@�r��@�ậj}�ePJln@������~xL�X�~�Y����JtX�յO�!�Rk��3�2O�0��ϓ�
A
N�wP���t��bR@I���ab|`iZ���t���ll"�@(�{m�p7�"Ԩ��E�G�q�Ո�
|��z ���$xT�=01�L@##CT�$r�P�G08�Ƴ�� ���Kf�����v��e��%��`�FN;��y�b82���9�Z���B�P��q�ּ�B�'�lA��Dx�n��N�Q�:�ͬ��T�h��Щ%����!�o�c|��O�O���]�B��6R�~�Q�)�J���9/�a�7�~�c�q7���:����;�{eV���C-7�9�a����Fq��65U�`��6Kv�>�����J�Fq���Ƽ�t��������=�۞̢�3���J�̔C�̕���b�:P���<# �L� �6H�}�[y:��9�CEX�v��ws7o�÷.=��n4dn�B�~U(?l��eQ"����ejm �>� �zC�����Pkx�Y�t0�R�}��)H�mrTNv��rS�-*�2���%�!y�^�p�}��p�ĝ_r��ꫴ�)4���m.�:k+���@�ʥ����6�wk*!!ĩ<ă��l1HlL�����T�+�3aڷ;Gc5�V%���S�$%�s�sٿ+�O�^��ewB�u��8q�J��3Ʃ��S�u��u�N|�%�؎�W���e��sIX�0Y�z�I��销��2P9���%��j��t:��P3��ko ����5�OjEI��m��Js�G�]<�!��Jea3�C!}G(�b�|�R��yp
���C
R{>x���gS~����;��~��S/ȜB?召!���ȸ6�c����*e031��%+�Q�P�z�hQ^�f~���&�R�2��
�G�i ˼,���`�_=4�aԘQ����}w{}jW�mD�M�
#M:�Q��T�A*���? �52��y���T}Ru7�@�a��J���t�3P @ӄ��� �� ��Z��o �Iu%���ˆ�I�����F+�S%�/8�J�͈Hv�ua:�Rc2�ϭI;WD��u�R �h7�b#�B�G���E�=Tz#�G�…�����ހ�n֥��AIX�9�8C#u�(s mE* 6#Q�޽�[�ry�����E���G� �n���Ϭa����j�t�fT��̴S�S�r�$�A�4&�R��ղ������D���m���iY�s��@=��Z%��
�hF��w���%B��"ֶ�T�]X}C<��c�@N��R�J:�u{bݝ�m�(�X��δD�i&�{��co8��u�D�o
��_����@yՖ������$�JVU����N4\k�z��Z��Ck)�=�����|��B�t��&��v�#�FZw�c�?m�j�gd���Tͩ�>�S��wQU-Q"[�)��kD��\Pn!ņ�� ��wWde����M����+ �ņQ�Ɣ�M,�)$��m�Y)7 ���x����#��U���ٞ�
�Qd����Ϲ���~Zy�}u�̬Ě�]M��q�4�JN��ܺ��o�Q�!^"�}�^ݬs�:cJf3�
0:�q�y���5;D�o�j������K�Ҭj#�]JQ�E8 ��q�]��g��%$f'Ud ��!��Z���w�չ#S�f)����z��ߙ{�S�4�[E�(T���L,�VYB�lQ�3��s���pR&��eRE��ߏ+n���Vn�0V��$h�}��%�;���&\�+�]
���#�G-6�2��/�C�2ځV�JҠF�k�� v@Ѝx�~Ge6NU�S�{D��;��7{M���/T�%�v�v �l�%;�f]N�^r�5Ǣ6�EE��
b\E�O�6l<�V:�'Y�6B����q�)�G���I�<~���j��fT���nˁ/��Iue�Z�1R�C�̄�� 8-'����y�P�a!��/3�&��v���!ր�����Ɵ;�pI��Mr�Ur�JոNb�$�?@��xB"�%x��k�vĆ@ ���KS>�Ρ'�3�A<���v���Jɗ���JS����� ��$932/��r
*�����Wg��w�{qpM����Y�+�m�������2I�� ��%e'�K ���-�����MI:��+!Yo�C�j�i{�p��嬌��I�J���4��q��{�kqT�Zۑ\�Bn� MăR[M���TBA�$�:-a*m:f��e*Uՙ�r�.,��%�n!����9@��1��m��<����Az��������<[3��d�҄� ��FĈ���V�]�΂��zùW%��aĦ��d�~�0#��G��x���p���ɟ�'A�o�x� �&ʃ���o;�@�; W=N:fTe�c�)!�EM�����mƵ�*G� <��8ʴ� \��Y!�x��o1�1}?�U;1��HM�Z��y��g��xݛ�v=}�յT��#���6��d����OD���ED�W� �>��J���u$��;ԣ���(�"�u|SQ3�6��|ԏ���s��Lk��9W_�O��x���gk�G��d����<�u ����:J��:����*���jM.U��5:|�Ǘ ��S�u)
J���r�ֆ�AK��ǫn�.�q��o����m�[�bo��I�k������A����V1�Si��*��vo2ISJ)��%�8�u�2���2W�a��n�� o���W싖Dž.��M��, �0��7�kqA!���!)Y� �J�ev�:�Y +��1&���w�u���^5۷���6�Q]�`�.+�zG���P���Q��0!~MQ��6P���
gјEТ�� |M�#�Hv��s��e��NR�ʒ��<-��+8���G�&�|�^�x��K5��h�D��Fh�i嚽�&У\����Qf�>�X��K�Q��uX%o:��Z�I$���4򄌒��(�ŕ,ܝ�3 E�iR��f%�G@ �h9˂��g�O�5ܐ,#Dze5��*��y��4�@s��OPB�}P�RG�כ���7���� z��/m���#u=ڻ�/���~߶W��b��(ƥ��KC�]�W�CyP
#�I�:��΍�d7��q��!���R��֖9��û�!���������u*ʚ�鰐��3K�JuZԯ*J�Z��J�I�,'�1`5kV7��QX��&�>O~�Дbrc�wg@�� |T5��U�kh1Z������?Al��p�pJ!�N��XY�w�$�-Dr�먥G��#Tqn�I��W̒-|�6=��d�8�t֐ܬ�BSl���\���1a�q@�[U�sӘ�^T�w7E �4�QJd��s�;�d�����T�w�f�eiL�³mdz�[��tU��Z� �e�u!.���rq �x�[+Q���d =�5
��Tv��J5�C���\K���7��Hя�P[�W�q�y��>P�[�1��Y��t�3X��eE��d`��A#A���Y�KN��$� ��Q)2�Ye)PЁ���ƛ�a�4{�R�ж�Y��IӣS�rl���2��:�u�Li�� 6��VT<m��.�9�F�M��8[F��N M���tE����~3�s ��?�H/+-��تl����(�
�J[4�2ZJ���J;�B�hJQ��3�8�>�'1v*\�A�JT⇬B���N���xG+�S �d;N`%ה����z�6� ���7^ ��m˽�(׆��*����Dm�@h������)Ds�� =R��� aaƩ�l%�
�J���9�p�I1W�&+��Ɇީ��� &�$Mɰ��y��+�Ġ�����BH�'�_�Rx�G“U�Z��R��3k�P#����褐A�k\����21�
$Ý��v�j���dW(�ސ����BP����q��O9<��`�낣9�,���͹w�)�U&���e}��� =��Ӽ���I�k��n"d
��r-�!�h}hKH�S�%}꒐�^L���0āK 妿�$��N4�Z�φ�����e�������p�b����ŰUX��_�Ta���z[H��e��ѥ%/�Fza\�!2*iԸ�6����?|HۦK�Ì��Q�7#p�!���cy¯dg�Id��
�ѱ|V�Tf�W��M@�N��8��a��a}u�����#jÀ�����;H�h+��Q�=G � 7/g��v��p�nע��aUN=���(He�M?݌e!kYO�8tNL�WB������"��J]h(sr_�.���H~��k�Ę�U��MV8NrR�
� �B\q���0s���� �8:���ʐy�q�`[{v/�E*{o�~͸���Q�&��=:�sd�H :���?�l��8b���I͗��y\B����2.vcZ�N�H��6cݔ� �sԸ;�A���zt���J�� 6+ �l�B���V]bU�}m���Ot3Z�Gp%l?����aĐ���$�~t�Ì��qd�����S ):�Z}�@��UOؽ�a='NW|�S耵uJG����dx湍�$�O�u��#01�iB����cd�"���E��������PV@���e@z-#���� ����� �6�?E�;$w�1#�x��1^fy� �8���=ڎb���n��Xt:����� ~ �{��IRU��Iq$cT����j�u!A�b �����.-W����JÙ��.<oX�V$� �N���uĠ1�T|�:y8q ��>� �J��ԫ>b3�������y� ��\V�GS�B�~�*o(O���:k4:]nj��%��I��y��4�Ԩ��71-�� �ᖼ ��:A��G`1� dF ����ͱ�X ��G�@ӽ*̿�!���_�L!*��-��F�AqƔ@�PI ��Z:�!���UJH=āIծ^M��R�;�$D��:��W�T���i��PQ _�\��WS����'/M����6��k�l�ΦÌW)���@�M:����$�� �@�Ϲ�B�"�U)]?^�|G\G'�
J���Ǡ$z�JI�1��(�V/J�۸�J��խ�� �%/��={���A�ȕ��ß�u襖��B1��.�mJ�m�����eujMF���) O�-IϘ)$dj�vӾ�"�W�"�&�JYJ��g����O�{���B��q���C�*P<͸�Ң�!c�RT0R��A�Y!*:FRJT6"7Lj���o6R���t�~�yCr�H��)����$�K�Nr�Bzsc#L5I $�y-��2#�]�)�T�u&e��s<�z��ȶ�&EsC�N߷V=Ŗ��u ^��Kg4��+�4�)Z�Y4����\w�J́$.$�e%ho���R��<N���I9HNϪ�;"���F�i+V��A����y��O~�c�3J`� +Ž
�m�q���:��:ZŠ��<�)��ޡ_��ҕנ̇4�Z�:�4����)Ϲ �jmCq[
l�0<�2�K����I��y�ۑ��Fd(Q��m=�%#�J8��B��j�2\�-F3�g���!J? s�{i X9�'�k\+mJ�!j�O�a�q��fRP�ϸ$r��F��f^VO՛��J�H�&���J~bkS��+�ғd�p�DN�}#��:k�?,kE�����!?�'�y�S����uU�.����6���^p��K<�� *yU�+I>�P�g8?�u��O�Ҍmɵe^�bу%�^�S܎���
W��\k��2�9��P�I-a��,��I�s�p�qE�՝�������L��u����y��F0VU� S�mc�Վ��1EqO��D�[h����(���%��J�% &����V6�ڸ��n8���� Ƌ)\�03�C~D�ԕg� R�����a�ⴘ�ZCM�a �������ׅ˦͡��UaIS̖�%���I�'�C88VFGLkU��f�k�)1�r) �3�<�ir��
�r�:,ac�= G^]NV�c(�[k��as&�E���s��r㍓����2|�
>�]a-��\g ��1�*��w-����|�B�ñ�ϋ��PT��s�-���%)��5E�O2r�;�HPRI�����cbU-�n|"e��zʂ�?19w�/+Ł@�����'J������L�]�7-�T֦IQ��\��FR�! �e @$�D�B�rl�\i!7Q�'As��(�Y�=\{s`̗��AK�)t�� tWQG�qa",P^t�א�'8K� *Z�G��u<����~q�E4�+r��L����}�6���� ޝJ4�Z��~�t�@��i�s��kd:�K����2S��̛"��=Y�!$ �@9[��9��g�?l�kn<��ۋZҖ�Q�,���C.�(�P ��\�L��R������p�%!D��y�G�p��Zm�t��<��M"�O�Iw�V�ȁ�KZ@��r��uC���7BÇe�Vx'?�����?��i��ao~�]��B�3�S�f�ӭ�!ܥHX
A
�:� Ɯ���T��'�����&���.Vq�!I��j�G(v���;��6
�kNSQr��F�""��C la`s/Ȝr�ޚ�Ү(�jEqe^B��)�^Չ'"-p-�,Sx��d��57�#������.!q����89u>�O�c���@օ��Q��Y���T�J����Q:ԒN���`�wn�_�o 9"�Y����9
��p�d}���ԯD��MqT*��'fU��`������9�����'[��M�� ���5<���~����6�ɹi�س�����̥���������W�a+���ss�IQS����\�l���6VNYIJYN�w� /�k��D�q�̃}[�6�@/g O��4�c"RGT��?oFwh��&[��=绛�2�������a�3-.��-���$u�mJ�i�ZH$�kfyÍ_��g���;�
�q/�s���2 ���U�N�1.�Ȯ�y��*����a�J@Zo��E��*;;r�(��;� ��-9�m�Іz��t=옯;�/�����)B���d�^���?��\>I|�z����S^�ˆ��'.�/�oM�s�
3Jf�(ÌiB�l~x��~Ѩ��))����ՉJ���.��3D��JK�#�%>�M��K�6u9��6�P���X��3l�C�ا�/<׷���Z )���Q�����-�h��Ot~���8�:�U��J {�4��Җ�&A$X߈��[
����
q�!/��o#�$(y���4�"\EŠ�W�<6�n�y[�VjͲ\b}}���R[*=�W����R�R*P�e�_Q��ee���g��|5��/��v�U'��*�.$
����i�:�Vۧ�Z��YmJ��`�$�낭=3OChj��3���BI���J��aa���B������m�iJ*�z�TI$�rI$�=DZ�YZ��̘�����B��ђr'W���R����3��OL��z�PWq��� ��
��:��ޱ���QS�[�2�th$���X��2�m
���+�(KJ��4�;,����h�$��np<�8fr��q���R;#x$���O�o��ڗt
����uj3�ܪ<�<�ւ��
T���OC�DdT�$)���-6�K�ڛj�S n(V���Y;%��Q�"����$'����N@�%I �Ԝu��$�����f�@��^:�0�~}{�(�I���W�ˏ��;d ,��ŏ�=T��|���Ns�� )p&J��Q�J%:.��b��?Yis:�c�����ɿ�W{(LKjK "�o�ݒ�U���<�9��)#��}4��T����H=���/�M��1$_C��R&bvhq�Bo�3o(�f8g�������VEV��)�jK^�ں)-����VI#�A��]�s�����x�u�᠇
��8]A+p�r����ΰ�o*�����L�b�'Ɵ>�t8�[�iۏ��#
�W�r��=2��� ����~W���O���9 dIV��x�)ºz�, �Np������yT ���"��?#;��")�,+-x�Cn�� �h^ �x��r3�(=?�����F����h���S�Ɋ�ߙ1m<mǐ��b
UrQm� j��'�Z�j�R���WS���Ǽ\E]�"�&)H�N�eY| �}���rSl�_WQ��c�͜��:6�|�'�\I� �Tm�N�̲��O���C�x��\Hۮ�9�������nN�
6��m吗*��'��C1�g�l�Mı* �w�՟ ��+�-|(}�5�����DL��וE�†T�k�G��C娥T�Wp��RUB@���*e�:6�W/7� E�nS`�}.TZz[�'���>��j2H���䠇Ծ 8���c?=j4�x��:�Ž�N>�-���Jl\��9S�S̕�K�U�ZG:RK�����#��e�Rԇ��w?u���'KH�۬I��"��^���ƢT��Z�&���j�i��y��Kl�m��m)ChO2��TI'P��������"TI��妙#�p2N�\q�z%�w�h��n��y<�ՠ�����BT�Т?`Z��K��)�+M�Z�t�"��R�>㕥�_��K��5�!b���՟}���z-�\�m?V��k�}�?���L�~�������3���9��h�Z��x;��1?ࣙ[�Q�ң� �;�����M�OF_8yv����d�hR��>CP���^ ����"g��~�9U�ܯ(`Ķ4�w�8R� ��q���"�}�'o h;%�WAJ��U��N����9�'�*d�q�sOa��#�����טi�d�� ���x�)��A�/Ü,�O��_� U{L��]�eF^V� ���y�}�Є���)V�GM{�Ι_\��Z�R��1��Ѭ����s��A���Q���J�ϗ�]H¬)EӘ�r9�&R���dN��D����x��-fm� ��)�����/�H�VGA�\S��&Xm.ٵ�k[�vJbf��Z��}uח(�\�CSoKn�g�1C�M��r$�t��.$�I�NA��|��-=�P���D�+J�B�xn��7]jzUr��%HX)P�Di��[Ws���*�X��f ��F�MiA���)s*PI P!@�j�a�A)^���-=e��n.�o�P��h����7A�-��]]�­���= ��k���&�C'�\
A��Ɵ����fl)@�p�ݸG�Y�1�@6��Q�Fc�gJ8��m�W�W|��P)� ��t�ԟbfJ[ >��H%�t��%dr�� l�K���D�Ved��i�l�n ����|�ض���j�m�r�W��p���4J�/�#��A����:�h�����N�jr7򎛧ŕ�e�2�\u�M����F�Xi��q�)���'�ԙ*�W^f];N�$s y�8q+ą��=���ΰ*M�X��(s�jG�Ge\�x`���\)��t�5,��B�)Q���8]Q��e.�&�JАx�'�aŠ�G*�2g�2]�q��_ ϟ(�t!�Ћ-X6���Bd�&ǪI�{���~ ����ײR�ш�u�>��0�YlBM_|S6#H(�� f��l���nGo'�RRˮt�$�6��"̴�k�=K*���$�p�J]Un ��A� ���ω�6��U�Ӷy" A�=��S���1��Q)L<��P�yB�p��t�}Ḽ��&ċ�B$��/�u�&��M�i����T�-)�>Ӯ~Z����p8Usk=c��VT��l�a|��(,�>��D���cG��fDt8�rR��?q鬂Rn2��c�tM�:�42���:��>�E�����Nui�le%��Ш�!� t�i��s��X�9F&�G���Q��g�w�y�>���G�=a#̍ka��
����JFIF��C 
  $.' ",#(7),01444'9=82<.342��C  2!!22222222222222222222222222222222222222222222222222����"��
���}!1AQa"q2���#B��R��$3br�
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz���������������������������������������������������������������������������
���w!1AQaq"2�B���� #3R�br�
$4�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�������������������������������������������������������������������������� ?�쉙�f�}�*˶6��i���V螃��$�/u?����tE�;���Npi��z�d/��5-rSF)���7cN=*l-&h&����@��g�yxIS�Үj)�Y�:��\��݀ >��N1�,�&�zbH�(d`A�W5 ̐�Zpj���QX΄���j���
�����(ᇵXI5��w'��/ ��nN"s�x��{z��{Ӕ�`Myo%�ɂp<��=EE[�f b��6���2�������r��QU�lKаzUy\2qN��&S�qH�K �Gq�E��^��Q�u�cx�ֳ �緪�qI�����Z��U��I���U��0�<d��<��TOb���Ǖ��rO�(�ϋ+q�L��
+�x����5GN;�Bz�S^���p*,cq���zv�n���ت��bH����c}�[�*�lb�9�J�9�[�%�rCDO(qVk6V6ڑn�ܟ�i���M[P��E4�Io��B�dR�+�x�`A�5�Z7�w �ݑO�E�Zj�vn����O?�ִ�m�nV����m�-������}�Oʹ�Q�vGR����#�nw�/<�Ţ|oPz��Y�ؖ�5̿ve�0{��������q�9��x�T�}�_�U�8p~F�[�����гE2��z�������e�XKg&���a�֖�ɴ����2�b���o~��K�c��0��D[8�Yʂ�?h�� Y]�9WCwo�4|�Qy�O����g|�a[,�ʺM'S6� 4m�<0��iBPw5RMX�� ��U����իkՔ�����t�+Ң��R��f�B����k����� A(N�Bk��ԏ���g[��WqI��0��l�N��VXYmn$��bHة�*��xłHpãV޸�l��V��`�W���ߍc���f���Uh�D�.wD7��s���Ws�{I�0h[꼏����*�y
�6K��?� Z}�1ѯ!�m2�Ӓ����1��=b��= ��k��#�o��������[�=M>�m�jL���j֚�l1 �#���7�nGn�mz����-��� 2 ��� �����6n�?���,d����4���teă�"�V�=y����}��[����?:[ �2���U�U[k�-��r���?�eH�iz��9�m���;�`�p�q&�w6)�$�Xé�4���\Ʃܑ:֟�"/�-M�O���8a]5�cR����̐��=�"�]��cyb�Md$o���I���B����`����DZ���h�/� ��#g�1��¤����x�u#�I�iI�V��݉"��K �q(2���O ��vf6����Һ�Zj^72�E���!�u#;~�݊�����zA,h?���\Uknd= G�:}�W�$/ӊ���8b� ����tK]N؛�����Vɓ����k�2{ �3�^���OZR���%E\xyQ���n���ٗ��>�� Ջn��﷚��u3g:����;]s��؎��ܝ L�m|�5Hz���G�F|�샕f�w�e����v��<�E����ͧ������F�Gc�kWX�/t��"�cpr������s� �!�����rF��o��=���5� ;!� ���o�%�e�~��]�����l�6\��sٿ��uoN�u����gA�ݏf���Y,�.Uѿ"(K�y�omQ�fd��h����� ���y�����>�4��-�k#Zx�P�P���"�g����[�}��?�bs�~֦q��=Z���Z��b����Ǜ o�����Ӳ+C�u,yQsZ?���S�b�b��/��U�?�}��^��(�[�-33[ܨ��2����@���Z~�xic�]¹���uj�=��p��,��p�z��W��%r��=F3`�š�����k�h]2�S�19�w��T���-��d��3$@G.;��?����iRCuw���ȸe��8$v :��s\G��f�-��l�I�E<�{z㨪zj �א����7m�d��J��i�ep��=��{�����%?)�SR���Jm;3Ps��[Z ��oq�o��5���<�<�j�nT�,��S7|Cd���:.J�= ��G�Z�>���PZI$��i2�Ea�d�;��
�������S뎟�[~ ��% '������֐��6���`���3B���Le�v�����Z�/��mM1:|�q ���k�����,���<�$��s�pA��-i��u:|�;�~#�����.IƷ�O���L��FV�c��_ʣԵ}sX����epg��,O��o�]�᛽N�k���f�
��r@�ں�<7adJ�f#����b��*�<F�@�a��k���Br|dV����<4uf����&e�����$g�z.��-�q�m�C ������_�cM᥮��4���d��ʭB2{�֩�m'��m���t��9 |��=A������MUȍ�@YF����g��k�����\\b���������gF�P�� ��Q�T' �����%U99��'O�����ta��Eh��>��#�'����0���G���\̐�7��U�IV�@���x�>����+��ϙ����'������� ���$W̷,��Z[����*�sm�nÉ!���,�[BL��l�nJvv=���ľ������(����i�\#��E�����2h7�u���$Z��� �F��������~����v �8�*o'R���~�5��Zgѣ^(�tHf�~�������Qg�ť$�ȫ<g�&�b���\��5�쫪C��3�}@b��T�қ;hf;<��_�RHR~��~5�8� �+���Đj�6�ܫiڤ@Kk,��r0?x�N֢��.�/m�����ߣ�:��ݩɡ�ܛG��I�0+��|��+�cM���?4ζ�kV���Pr1ѐ�A�����r�CxR��Ih�C�џOq�z�+^�ޏ7+�B�4r�*��� ���N�ƿ3���a�Ϩ��u��j�څ��u53ٿ��A��4�h�#ʖbSɛ��CW�.w*C��v^!����2�y�FH��+����-$��t"�S�ք���/^��%S��=Eu�K�Cq��(����[�B���W�Y��9x=�ֺ�&�J��UV ���2���r���\�J��E��:��Z�qo ��4�����סh��ӡO5�z"���U|'ir��œ�Dl�J���k��8�&��H�v#�#d�S���Hj �� �ByW^�{\��n��O�
�_냀}���;#&?�ج��d?3���W �n�˃L�_��I�Z�ׯuf�'��Q�j�j��Q��V�<+�����7r�av���#/\zsZJ*�������Mf�$w�d��� x?�8�L�?ͣK���;+m:�-�aX�N�w�>��|T�ts�dQ��srw;��D� Ki��������YZT��W����F�t�CZ��e��ć��[��ґ�g5̺�����-�<��BcoÊ�d0y���E��28�ΪX������F�+��vfos�t��m?����a� �_�������Ћ��^t�Pzٟ�+�RR`އ��t��h��c�[m��T"���K�x�q��p~���Efy�ޱ�q:.��� W�+��+��Pj��)���<�4O�C��Gv� ����B����~��u ��;�?0_��i�vc>��o��t����sס?C�kN�� B����![ y���z;�㱹}���3w�p��޻ۻ�ėL#���枑��}����F��Y�v�k��i��-�/�g�98>����\�s��t��_��z��T|C�i�Zv�eᝯc��H�p��t>�{��H�."��x���ՙ� &�s�>�=��e�B�mc������[W�6��@�*���" ��*ZjJ|������^�#�nt��˳���U��±ZV8O�FM*pу�Ɏ�ʲl�e�EG �0T�>��6��%�t�gH���*:�V�+�:M��S�n�T��c����܇=C�n��6�$ym����Ȯ�j6�;߶�
���=��ݔ��l��{s]�6{�f����L�:��8��&�
�=��!�;Q�� ���#9�*0sEщQ��o�Y�r�- o19�@����:ѣ��m��TR�3\��.BZAz�s� WRFk�|g{�_������ir��n��ȗ?Vb��U �S�#�Շ�H�[��f�0J��'�������9��q�X}kX�̌�d�T, �~��?��-�v���}��qO�QE�����"������C�j*��%?���l�E�^���Ax�W|5��jZ�Ɍ�Ղ��?�e��{�c���wը����mft^ �W@��$a�'�p�<��y��$���
�A9��A�l�������rd�:�c ��n�{FKK�y�9��+*UEg�u#etu��[_YkHU�H�n��/�'���4���X>����Ȼ|�g#�t�5��izf�e�iA��ku3�N�<���L�P�H�q�?J� Uݫ�%MJ:��ZX������=���������hK��-��$bIջ����^{k�:��Y��J����Pg�2�߽uի)�gN�i� 8�ҀsJS�kS���R�ND(��T}��X��F�M���m �1WV!��V<}�?h# ��8�B�R��T�r����B��P�sN�%>�,)(�K@]ζ����I�!ץv�lϯ<���z�{��N��;��uGs^c�\�u��a��h����r��31Py�z
k.g�S�;�8�OJr��湆�����5�l���+��i#{�Y֜���k�l��{���O���)���)�?��k�\S�AW�v'��x��h����?�<�%�]3�+_wE�35=0O#�5�@���A�5
��Vv��G����2|�9�}>���o}�fJ���� �}�C���17���5��� ߊ�H����;��:����� ��ޫ�m+"�a�8�?���,׭�j1����n9��#�*��)�2���n��m쥌�=�k)����X�E��+�fe �����T�4� �rpG�ד����ʇ���U����S݉�x1l�f�K���v�d���q� xť��D���_�A�K}cP� $��ć�f�^[��1� �\߇/����y�A�������j ֔�i�<u[{z �Jf��Qc����,��*���,�HGL��U��!B��y�4��"���L��č/���x�� �6��f-�ƶ��������R;�B�8'�M�=E�
��*����f�o������b���U{�=�5<At�n�4�������G��>��r`mN���vW��1�e��긷�����![��5��uNj$�¤n��I�Ņ�/�m'�����ʑF�I,�d����j�s! �"�y9��O�2�wm�ڱ�c��@��P�?��P��8$�qUK�ի/�j*a�� E I�{͗�x����E�?��m�\S�AWʳҎ“L3�ٟ��N�O�!<��v2o�?�#Ms;��mGUTzc��i�gP�A�f��e����Zt���Vaʄ��E ���R�kƼMp.�/g�������cX�L�g�+�1ܱ�W�k��t���:�v_z��:�R{9�/*xe=묵���1,M�Q�}kϋ�j�����ʰ�k�q�rB����~� �N[Q�&���=kq�I\�$���|D �2y3�A�?�^��x�V+���Q��+E�d���AڻT=�w�ŝ��4�ɏ�h2ߏ��R�kG����T��=}���Krn�fc�ظQ���[a�F��"f�Z�s⫉إ����?3~-�~���>�e%�I�3^me�\Z;)
���+�ҵ�{ҩ."����?C^�T���r�������2}O5%
8��[��mK'9�cD]���P����Il&bx���f�̇'�+���[�"�j9X���k�-�\��� �J�b~z�*�̄W-���{��� o�����l-���"��랔v�(�3e���QP�s���{���V��'��#���:ԧz�I8�=�W����Ę}�����p�#�<װ��-��A�&�*%�pv:�#]�
���$,Ǒ�?���c�!�c�0�_o�,:�;gҊ(������$�8�PLAQ^���:}/_�����?�c����#��e
�7n(�� �95����WW� 9? QEm�
�>$����Jq�e^x�i��F71ɢ��M���;9�d�Q����)
N1Wl� QXW�ks�����qO�QE��sӎ���
$(function(){
$('#loginbox td img').click(function(event) {
/* Act on the event */
$(this).attr('src', VERIFY_URL+Math.random());
return false;
});
$('#adminsider a').each(function(index, el) {
if(!$(this).hasClass('logout')&&!$(this).hasClass('pwd')){
$(this).click(function(event) {
/* Act on the event */
$('#adminsider a').removeClass('this');
$(this).addClass('this');
$('.admin_box iframe').show();
$('.admin_box #repwd').hide();
resrc=$(this).attr('href');
$('.admin_box iframe').attr('src', resrc);
return false;
});
}
});
$('#adminsider a.pwd').click(function(event) {
/* Act on the event */
$('#adminsider a').removeClass('this');
$(this).addClass('this');
$('.admin_box iframe').hide();
$('.admin_box #repwd').show();
return false;
});
$('#repwd .submit').click(function(event) {
/* Act on the event */
if($('#repwd .password').val()!=$('#repwd .repassword').val()){
alert('两次输入不一样');
return false;
}
});
if ( $.browser.msie ){
if($.browser.version!='6.0'){
$('#body_bg').load('http://pic.uuhy.com/uploads/2011/05/23/Xmas_Wallpaper_08___White_by_bm.jpg',function(){
$(this).fadeOut(200).delay(200).css({'background-attachment':'fixed','background-position':'center top','background-repeat':'no-repeat','background-image':'url(http://pic.uuhy.com/uploads/2011/05/23/Xmas_Wallpaper_08___White_by_bm.jpg)'}).fadeIn(1000);
});
}
}
else{
$('#body_bg').load('http://pic.uuhy.com/uploads/2011/05/23/Xmas_Wallpaper_08___White_by_bm.jpg',function(){
$(this).fadeOut(200).delay(200).css({'background-attachment':'fixed','background-position':'center top','background-repeat':'no-repeat','background-image':'url(http://pic.uuhy.com/uploads/2011/05/23/Xmas_Wallpaper_08___White_by_bm.jpg)'}).fadeIn(1000);
});
}
$('#sider').delay(10000).animate({
top: '40px',},
1000, function() {
$('#ad').fadeIn('slow');
});
});
/*! jQuery v1.7.2 jquery.com | jquery.org/license */
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
/* CSS Document */
*html{
background-image:url(about:blank);
background-attachment:fixed;
}
*{
margin:0;
padding:0;
font-size:14px;
font-family:"微软雅黑";
text-decoration:none;
color:#5c5c5c;
list-style:none;
border: 0;
}
input,select{
}
.clear{
clear:both;
}
body{
background:#CCC;
}
#box{
width:860px;
height:100%;
margin:auto;
}
#body_bg {
display: none;
height: 100%;
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: -2;
}
#left{
width:200px;
height:500px;
float:left;
}
#left #sider{
border-radius: 5px;
position:fixed;
width:200px;
top:100px;
background:#fff;
_position:absolute;
_top:expression(eval(document.documentElement.scrollTop+100));
}
#left #ad{
display: none;
position:fixed;
width:200px;
height: 200px;
overflow: hidden;
top:320px;
background:#fff;
_position:absolute;
_top:expression(eval(document.documentElement.scrollTop+100));
}
#left #adminsider{
position:fixed;
width:200px;
top:100px;
background:#fff;
_position:absolute;
_top:expression(eval(document.documentElement.scrollTop+100));
}
#left #adminsider span{
display: block;
font-size: 26px;
text-align: center;
line-height: 30px;
}
#left #adminsider a{
margin-top: 1px;
background: #7f5;
display: block;
text-align: center;
line-height: 22px;
}
#left #adminsider a:hover{
background: #7ff;
}
#left #adminsider a.this{
background: #7ff;
}
#left #adminsider p{
font-size: 12px;
text-align: center;
line-height: 30px;
margin-bottom: 20px;
}
#left #sider img{
display:block;
margin:25px;
}
#left #sider ul{
text-align:center;
}
#left #sider li{
line-height:30px;
height:30px;
display:inline;
}
#left #sider li a{
padding-left:5px;
padding-right:5px;
font-size:16px;
}
#left #sider p{
line-height:40px;
height:40px;
text-align:center;
}
#right{
overflow:hidden;
width:660px;
float:left;
margin-bottom:40px;
}
#right .pas_box{
border-radius: 5px;
margin:10px;
width:620px;
padding:10px;
height:400px;
background:#fff;
}
#right .pas_box h3 b{
float: right;
}
#right .pas_box p span.count{
float: right;
}
#paging{
text-align: center;
width:620px;
padding:10px;
margin:10px;
line-height: 20px;
}
#paging a,#paging span{
padding: 5px;
padding-left: 10px;
padding-right: 10px;
background: #fff;
}
#paging span{
background: #ff0;
}
#right .admin_box{
position: relative;
border-radius: 5px;
margin:10px;
width:620px;
padding:10px;
height:600px;
background:#fff;
}
#right .item_pas{
border-radius: 5px;
overflow: hidden;
width:640px;
margin:10px;
background:#fff;
}
#right .item_pas .thumb{
width:200px;
height:150px;
margin-left:10px;
_margin-left:5px;
margin-right:10px;
margin-bottom:10px;
display:block;
float:left;
}
#right .item_pas .intro{
overflow:hidden;
width:410px;
height:150px;
float:left;
}
#right .item_pas p{
overflow:hidden;
width:410px;
height:120px;
line-height:20px;
display:block;
float:left;
}
#right .item_pas ul{
text-align:right;
overflow:hidden;
width:410px;
line-height:30px;
height:30px;
display:block;
float:left;
}
#right .item_pas li{
line-height:30px;
display:inline;
}
#right .item_pas h3{
display:block;
width:640px;
height:30px;
line-height:30px;
padding-left:10px;
}
#right .item_pas h3 span{
float:right;
margin-right:20px;
font-weight:normal;
}
#right .item_img{
width:200px;
height:200px;
margin:10px;
float:left;
margin:10px;
_margin:8px;
_margin-left:7px;
}
#footer{
border-radius: 5px 5px 0 0;
height:40px;
background:#3CF;
position:fixed;
bottom:0;
width:860px;
_position:absolute;
_bottom:auto;
_top:expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.offsetHeight-(parseInt(this.currentStyle.marginTop,10)||0)-(parseInt(this.currentStyle.marginBottom,10)||0)));
}
#cri{
display: none;
border-radius: 5px 5px 0 0;
height:40px;
background:#3CF;
position:fixed;
bottom:0;
width:860px;
_position:absolute;
_bottom:auto;
_top:expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.offsetHeight-(parseInt(this.currentStyle.marginTop,10)||0)-(parseInt(this.currentStyle.marginBottom,10)||0)));
}
#footer a{
line-height: 40px;
font-size: 14px;
float: right;
margin-right: 10px;
color: #fff;
}
#footer b{
line-height: 40px;
font-size: 20px;
color: #fff;
margin-left: 10px;
}
.table{
width: 100%;
}
.table td{
line-height: 30px;
}
.table td.des{
line-height: 50px;
}
.table td.content td{
line-height: normal !important;
}
#loginbox{
padding: 10px;
background: #fff;
width: 280px;
height: 120px;
position:absolute;
top: 50%;
left: 50%;
margin:-60px 0 0 -140px;
}
#loginbox input{
border: 1px solid #0f0;
}
#loginbox input.verify{
width: 80px;
}
#loginbox td img{
cursor: pointer;
margin-left: 10px;
vertical-align: middle;
}
#in_box{
position: relative;
width: 620px;
height: 600px;
background: #fff;
}
#in_box #blognew input,#in_box #blognew textarea,#in_box #blognew select{
font-size: 12px;
overflow-y:hidden;
resize:none;
width: 100%;
border: 1px solid #0f0 !important;
vertical-align: middle;
}
#in_box #blognew textarea.des{
width: 500px;
}
#in_box #blognew input.submit{
width: 50%;
}
#in_box #blognew td.submit{
text-align: center;
}
#repwd{
display: none;
position: absolute;
width: 300px;
height: 110px;
border: 1px solid #0f0;
top: 50%;
left: 50%;
margin: -55px 0 0 -150px;
}
#repwd input{
border: 1px solid #f0f;
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Think 基础函数库
* @category Think
* @package Common
* @author liu21st <liu21st@gmail.com>
*/
/**
* 获取模版文件 格式 项目://分组@主题/模块/操作
* @param string $name 模版资源地址
* @param string $layer 视图层(目录)名称
* @return string
*/
function T($template='',$layer=''){
if(is_file($template)) {
return $template;
}
// 解析模版资源地址
if(false === strpos($template,'://')){
$template = APP_NAME.'://'.str_replace(':', '/',$template);
}
$info = parse_url($template);
$file = $info['host'].(isset($info['path'])?$info['path']:'');
$group = isset($info['user'])?$info['user'].'/':(defined('GROUP_NAME')?GROUP_NAME.'/':'');
$app = $info['scheme'];
$layer = $layer?$layer:C('DEFAULT_V_LAYER');
// 获取当前主题的模版路径
if(($list = C('EXTEND_GROUP_LIST')) && isset($list[$app])){ // 扩展分组
$baseUrl = $list[$app].'/'.$group.$layer.'/';
}elseif(1==C('APP_GROUP_MODE')){ // 独立分组模式
$baseUrl = dirname(BASE_LIB_PATH).'/'.$group.$layer.'/';
}else{
$baseUrl = TMPL_PATH.$group;
}
// 分析模板文件规则
if('' == $file) {
// 如果模板文件名为空 按照默认规则定位
$file = MODULE_NAME . C('TMPL_FILE_DEPR') . ACTION_NAME;
}elseif(false === strpos($file, '/')){
$file = MODULE_NAME . C('TMPL_FILE_DEPR') . $file;
}
return $baseUrl.$file.C('TMPL_TEMPLATE_SUFFIX');
}
/**
* 获取输入参数 支持过滤和默认值
* 使用方法:
* <code>
* I('id',0); 获取id参数 自动判断get或者post
* I('post.name','','htmlspecialchars'); 获取$_POST['name']
* I('get.'); 获取$_GET
* </code>
* @param string $name 变量的名称 支持指定类型
* @param mixed $default 不存在的时候默认值
* @param mixed $filter 参数过滤方法
* @return mixed
*/
function I($name,$default='',$filter=null) {
if(strpos($name,'.')) { // 指定参数来源
list($method,$name) = explode('.',$name,2);
}else{ // 默认为自动判断
$method = 'param';
}
switch(strtolower($method)) {
case 'get' : $input =& $_GET;break;
case 'post' : $input =& $_POST;break;
case 'put' : parse_str(file_get_contents('php://input'), $input);break;
case 'param' :
switch($_SERVER['REQUEST_METHOD']) {
case 'POST':
$input = $_POST;
break;
case 'PUT':
parse_str(file_get_contents('php://input'), $input);
break;
default:
$input = $_GET;
}
if(C('VAR_URL_PARAMS') && isset($_GET[C('VAR_URL_PARAMS')])){
$input = array_merge($input,$_GET[C('VAR_URL_PARAMS')]);
}
break;
case 'request' : $input =& $_REQUEST; break;
case 'session' : $input =& $_SESSION; break;
case 'cookie' : $input =& $_COOKIE; break;
case 'server' : $input =& $_SERVER; break;
case 'globals' : $input =& $GLOBALS; break;
default:
return NULL;
}
// 全局过滤
// array_walk_recursive($input,'filter_exp');
if(C('VAR_FILTERS')) {
$_filters = explode(',',C('VAR_FILTERS'));
foreach($_filters as $_filter){
// 全局参数过滤
array_walk_recursive($input,$_filter);
}
}
if(empty($name)) { // 获取全部变量
$data = $input;
$filters = isset($filter)?$filter:C('DEFAULT_FILTER');
if($filters) {
$filters = explode(',',$filters);
foreach($filters as $filter){
$data = array_map($filter,$data); // 参数过滤
}
}
}elseif(isset($input[$name])) { // 取值操作
$data = $input[$name];
$filters = isset($filter)?$filter:C('DEFAULT_FILTER');
if($filters) {
$filters = explode(',',$filters);
foreach($filters as $filter){
if(function_exists($filter)) {
$data = is_array($data)?array_map($filter,$data):$filter($data); // 参数过滤
}else{
$data = filter_var($data,is_int($filter)?$filter:filter_id($filter));
if(false === $data) {
return isset($default)?$default:NULL;
}
}
}
}
}else{ // 变量默认值
$data = isset($default)?$default:NULL;
}
return $data;
}
/**
* 记录和统计时间(微秒)和内存使用情况
* 使用方法:
* <code>
* G('begin'); // 记录开始标记位
* // ... 区间运行代码
* G('end'); // 记录结束标签位
* echo G('begin','end',6); // 统计区间运行时间 精确到小数后6位
* echo G('begin','end','m'); // 统计区间内存使用情况
* 如果end标记位没有定义,则会自动以当前作为标记位
* 其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
* </code>
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位或者m
* @return mixed
*/
function G($start,$end='',$dec=4) {
static $_info = array();
static $_mem = array();
if(is_float($end)) { // 记录时间
$_info[$start] = $end;
}elseif(!empty($end)){ // 统计时间和内存使用
if(!isset($_info[$end])) $_info[$end] = microtime(TRUE);
if(MEMORY_LIMIT_ON && $dec=='m'){
if(!isset($_mem[$end])) $_mem[$end] = memory_get_usage();
return number_format(($_mem[$end]-$_mem[$start])/1024);
}else{
return number_format(($_info[$end]-$_info[$start]),$dec);
}
}else{ // 记录时间和内存使用
$_info[$start] = microtime(TRUE);
if(MEMORY_LIMIT_ON) $_mem[$start] = memory_get_usage();
}
}
/**
* 设置和获取统计数据
* 使用方法:
* <code>
* N('db',1); // 记录数据库操作次数
* N('read',1); // 记录读取次数
* echo N('db'); // 获取当前页面数据库的所有操作次数
* echo N('read'); // 获取当前页面读取次数
* </code>
* @param string $key 标识位置
* @param integer $step 步进值
* @return mixed
*/
function N($key, $step=0,$save=false) {
static $_num = array();
if (!isset($_num[$key])) {
$_num[$key] = (false !== $save)? S('N_'.$key) : 0;
}
if (empty($step))
return $_num[$key];
else
$_num[$key] = $_num[$key] + (int) $step;
if(false !== $save){ // 保存结果
S('N_'.$key,$_num[$key],$save);
}
}
/**
* 字符串命名风格转换
* type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
* @param string $name 字符串
* @param integer $type 转换类型
* @return string
*/
function parse_name($name, $type=0) {
if ($type) {
return ucfirst(preg_replace("/_([a-zA-Z])/e", "strtoupper('\\1')", $name));
} else {
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
}
}
/**
* 优化的require_once
* @param string $filename 文件地址
* @return boolean
*/
function require_cache($filename) {
static $_importFiles = array();
if (!isset($_importFiles[$filename])) {
if (file_exists_case($filename)) {
require $filename;
$_importFiles[$filename] = true;
} else {
$_importFiles[$filename] = false;
}
}
return $_importFiles[$filename];
}
/**
* 批量导入文件 成功则返回
* @param array $array 文件数组
* @param boolean $return 加载成功后是否返回
* @return boolean
*/
function require_array($array,$return=false){
foreach ($array as $file){
if (require_cache($file) && $return) return true;
}
if($return) return false;
}
/**
* 区分大小写的文件存在判断
* @param string $filename 文件地址
* @return boolean
*/
function file_exists_case($filename) {
if (is_file($filename)) {
if (IS_WIN && C('APP_FILE_CASE')) {
if (basename(realpath($filename)) != basename($filename))
return false;
}
return true;
}
return false;
}
/**
* 导入所需的类库 同java的Import 本函数有缓存功能
* @param string $class 类库命名空间字符串
* @param string $baseUrl 起始路径
* @param string $ext 导入的文件扩展名
* @return boolean
*/
function import($class, $baseUrl = '', $ext='.class.php') {
static $_file = array();
$class = str_replace(array('.', '#'), array('/', '.'), $class);
if ('' === $baseUrl && false === strpos($class, '/')) {
// 检查别名导入
return alias_import($class);
}
if (isset($_file[$class . $baseUrl]))
return true;
else
$_file[$class . $baseUrl] = true;
$class_strut = explode('/', $class);
if (empty($baseUrl)) {
$libPath = defined('BASE_LIB_PATH')?BASE_LIB_PATH:LIB_PATH;
if ('@' == $class_strut[0] || APP_NAME == $class_strut[0]) {
//加载当前项目应用类库
$baseUrl = dirname($libPath);
$class = substr_replace($class, basename($libPath).'/', 0, strlen($class_strut[0]) + 1);
}elseif ('think' == strtolower($class_strut[0])){ // think 官方基类库
$baseUrl = CORE_PATH;
$class = substr($class,6);
}elseif (in_array(strtolower($class_strut[0]), array('org', 'com'))) {
// org 第三方公共类库 com 企业公共类库
$baseUrl = LIBRARY_PATH;
}else { // 加载其他项目应用类库
$class = substr_replace($class, '', 0, strlen($class_strut[0]) + 1);
$baseUrl = APP_PATH . '../' . $class_strut[0] . '/'.basename($libPath).'/';
}
}
if (substr($baseUrl, -1) != '/')
$baseUrl .= '/';
$classfile = $baseUrl . $class . $ext;
if (!class_exists(basename($class),false)) {
// 如果类不存在 则导入类库文件
return require_cache($classfile);
}
}
/**
* 基于命名空间方式导入函数库
* load('@.Util.Array')
* @param string $name 函数库命名空间字符串
* @param string $baseUrl 起始路径
* @param string $ext 导入的文件扩展名
* @return void
*/
function load($name, $baseUrl='', $ext='.php') {
$name = str_replace(array('.', '#'), array('/', '.'), $name);
if (empty($baseUrl)) {
if (0 === strpos($name, '@/')) {
//加载当前项目函数库
$baseUrl = COMMON_PATH;
$name = substr($name, 2);
} else {
//加载ThinkPHP 系统函数库
$baseUrl = EXTEND_PATH . 'Function/';
}
}
if (substr($baseUrl, -1) != '/')
$baseUrl .= '/';
require_cache($baseUrl . $name . $ext);
}
/**
* 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
* @param string $class 类库
* @param string $baseUrl 基础目录
* @param string $ext 类库后缀
* @return boolean
*/
function vendor($class, $baseUrl = '', $ext='.php') {
if (empty($baseUrl))
$baseUrl = VENDOR_PATH;
return import($class, $baseUrl, $ext);
}
/**
* 快速定义和导入别名 支持批量定义
* @param string|array $alias 类库别名
* @param string $classfile 对应类库
* @return boolean
*/
function alias_import($alias, $classfile='') {
static $_alias = array();
if (is_string($alias)) {
if(isset($_alias[$alias])) {
return require_cache($_alias[$alias]);
}elseif ('' !== $classfile) {
// 定义别名导入
$_alias[$alias] = $classfile;
return;
}
}elseif (is_array($alias)) {
$_alias = array_merge($_alias,$alias);
return;
}
return false;
}
/**
* D函数用于实例化Model 格式 项目://分组/模块
* @param string $name Model资源地址
* @param string $layer 业务层名称
* @return Model
*/
function D($name='',$layer='') {
if(empty($name)) return new Model;
static $_model = array();
$layer = $layer?$layer:C('DEFAULT_M_LAYER');
if(strpos($name,'://')) {// 指定项目
list($app) = explode('://',$name);
$name = str_replace('://','/'.$layer.'/',$name);
}else{
$app = C('DEFAULT_APP');
$name = $app.'/'.$layer.'/'.$name;
}
if(isset($_model[$name])) return $_model[$name];
$path = explode('/',$name);
if($list = C('EXTEND_GROUP_LIST') && isset($list[$app])){ // 扩展分组
$baseUrl = $list[$app];
import($path[2].'/'.$path[1].'/'.$path[3].$layer,$baseUrl);
}elseif(count($path)>3 && 1 == C('APP_GROUP_MODE')) { // 独立分组
$baseUrl = $path[0]== '@' ? dirname(BASE_LIB_PATH) : APP_PATH.'../'.$path[0].'/'.C('APP_GROUP_PATH').'/';
import($path[2].'/'.$path[1].'/'.$path[3].$layer,$baseUrl);
}else{
import($name.$layer);
}
$class = basename($name.$layer);
if(class_exists($class)) {
$model = new $class(basename($name));
}else {
$model = new Model(basename($name));
}
$_model[$name] = $model;
return $model;
}
/**
* M函数用于实例化一个没有模型文件的Model
* @param string $name Model名称 支持指定基础模型 例如 MongoModel:User
* @param string $tablePrefix 表前缀
* @param mixed $connection 数据库连接信息
* @return Model
*/
function M($name='', $tablePrefix='',$connection='') {
static $_model = array();
if(strpos($name,':')) {
list($class,$name) = explode(':',$name);
}else{
$class = 'Model';
}
$guid = $tablePrefix . $name . '_' . $class;
if (!isset($_model[$guid]))
$_model[$guid] = new $class($name,$tablePrefix,$connection);
return $_model[$guid];
}
/**
* A函数用于实例化Action 格式:[项目://][分组/]模块
* @param string $name Action资源地址
* @param string $layer 控制层名称
* @param boolean $common 是否公共目录
* @return Action|false
*/
function A($name,$layer='',$common=false) {
static $_action = array();
$layer = $layer?$layer:C('DEFAULT_C_LAYER');
if(strpos($name,'://')) {// 指定项目
list($app) = explode('://',$name);
$name = str_replace('://','/'.$layer.'/',$name);
}else{
$app = '@';
$name = '@/'.$layer.'/'.$name;
}
if(isset($_action[$name])) return $_action[$name];
$path = explode('/',$name);
if($list = C('EXTEND_GROUP_LIST') && isset($list[$app])){ // 扩展分组
$baseUrl = $list[$app];
import($path[2].'/'.$path[1].'/'.$path[3].$layer,$baseUrl);
}elseif(count($path)>3 && 1 == C('APP_GROUP_MODE')) { // 独立分组
$baseUrl = $path[0]== '@' ? dirname(BASE_LIB_PATH) : APP_PATH.'../'.$path[0].'/'.C('APP_GROUP_PATH').'/';
import($path[2].'/'.$path[1].'/'.$path[3].$layer,$baseUrl);
}elseif($common) { // 加载公共类库目录
import(str_replace('@/','',$name).$layer,LIB_PATH);
}else{
import($name.$layer);
}
$class = basename($name.$layer);
if(class_exists($class,false)) {
$action = new $class();
$_action[$name] = $action;
return $action;
}else {
return false;
}
}
/**
* 远程调用模块的操作方法 URL 参数格式 [项目://][分组/]模块/操作
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @return mixed
*/
function R($url,$vars=array(),$layer='') {
$info = pathinfo($url);
$action = $info['basename'];
$module = $info['dirname'];
$class = A($module,$layer);
if($class){
if(is_string($vars)) {
parse_str($vars,$vars);
}
return call_user_func_array(array(&$class,$action.C('ACTION_SUFFIX')),$vars);
}else{
return false;
}
}
/**
* 获取和设置语言定义(不区分大小写)
* @param string|array $name 语言变量
* @param string $value 语言值
* @return mixed
*/
function L($name=null, $value=null) {
static $_lang = array();
// 空参数返回所有定义
if (empty($name))
return $_lang;
// 判断语言获取(或设置)
// 若不存在,直接返回全大写$name
if (is_string($name)) {
$name = strtoupper($name);
if (is_null($value))
return isset($_lang[$name]) ? $_lang[$name] : $name;
$_lang[$name] = $value; // 语言定义
return;
}
// 批量定义
if (is_array($name))
$_lang = array_merge($_lang, array_change_key_case($name, CASE_UPPER));
return;
}
/**
* 获取和设置配置参数 支持批量定义
* @param string|array $name 配置变量
* @param mixed $value 配置值
* @return mixed
*/
function C($name=null, $value=null) {
static $_config = array();
// 无参数时获取所有
if (empty($name)) {
if(!empty($value) && $array = S('c_'.$value)) {
$_config = array_merge($_config, array_change_key_case($array));
}
return $_config;
}
// 优先执行设置获取或赋值
if (is_string($name)) {
if (!strpos($name, '.')) {
$name = strtolower($name);
if (is_null($value))
return isset($_config[$name]) ? $_config[$name] : null;
$_config[$name] = $value;
return;
}
// 二维数组设置和获取支持
$name = explode('.', $name);
$name[0] = strtolower($name[0]);
if (is_null($value))
return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
$_config[$name[0]][$name[1]] = $value;
return;
}
// 批量设置
if (is_array($name)){
$_config = array_merge($_config, array_change_key_case($name));
if(!empty($value)) {// 保存配置值
S('c_'.$value,$_config);
}
return;
}
return null; // 避免非法参数
}
/**
* 处理标签扩展
* @param string $tag 标签名称
* @param mixed $params 传入参数
* @return mixed
*/
function tag($tag, &$params=NULL) {
// 系统标签扩展
$extends = C('extends.' . $tag);
// 应用标签扩展
$tags = C('tags.' . $tag);
if (!empty($tags)) {
if(empty($tags['_overlay']) && !empty($extends)) { // 合并扩展
$tags = array_unique(array_merge($extends,$tags));
}elseif(isset($tags['_overlay'])){ // 通过设置 '_overlay'=>1 覆盖系统标签
unset($tags['_overlay']);
}
}elseif(!empty($extends)) {
$tags = $extends;
}
if($tags) {
if(APP_DEBUG) {
G($tag.'Start');
trace('[ '.$tag.' ] --START--','','INFO');
}
// 执行扩展
foreach ($tags as $key=>$name) {
if(!is_int($key)) { // 指定行为类的完整路径 用于模式扩展
$name = $key;
}
B($name, $params);
}
if(APP_DEBUG) { // 记录行为的执行日志
trace('[ '.$tag.' ] --END-- [ RunTime:'.G($tag.'Start',$tag.'End',6).'s ]','','INFO');
}
}else{ // 未执行任何行为 返回false
return false;
}
}
/**
* 动态添加行为扩展到某个标签
* @param string $tag 标签名称
* @param string $behavior 行为名称
* @param string $path 行为路径
* @return void
*/
function add_tag_behavior($tag,$behavior,$path='') {
$array = C('tags.'.$tag);
if(!$array) {
$array = array();
}
if($path) {
$array[$behavior] = $path;
}else{
$array[] = $behavior;
}
C('tags.'.$tag,$array);
}
/**
* 执行某个行为
* @param string $name 行为名称
* @param Mixed $params 传入的参数
* @return void
*/
function B($name, &$params=NULL) {
if(strpos($name,'/')){
list($name,$method) = explode('/',$name);
}else{
$method = 'run';
}
$class = $name.'Behavior';
if(APP_DEBUG) {
G('behaviorStart');
}
$behavior = new $class();
$behavior->$method($params);
if(APP_DEBUG) { // 记录行为的执行日志
G('behaviorEnd');
trace($name.' Behavior ::'.$method.' [ RunTime:'.G('behaviorStart','behaviorEnd',6).'s ]','','INFO');
}
}
/**
* 去除代码中的空白和注释
* @param string $content 代码内容
* @return string
*/
function strip_whitespace($content) {
$stripStr = '';
//分析php源码
$tokens = token_get_all($content);
$last_space = false;
for ($i = 0, $j = count($tokens); $i < $j; $i++) {
if (is_string($tokens[$i])) {
$last_space = false;
$stripStr .= $tokens[$i];
} else {
switch ($tokens[$i][0]) {
//过滤各种PHP注释
case T_COMMENT:
case T_DOC_COMMENT:
break;
//过滤空格
case T_WHITESPACE:
if (!$last_space) {
$stripStr .= ' ';
$last_space = true;
}
break;
case T_START_HEREDOC:
$stripStr .= "<<<THINK\n";
break;
case T_END_HEREDOC:
$stripStr .= "THINK;\n";
for($k = $i+1; $k < $j; $k++) {
if(is_string($tokens[$k]) && $tokens[$k] == ';') {
$i = $k;
break;
} else if($tokens[$k][0] == T_CLOSE_TAG) {
break;
}
}
break;
default:
$last_space = false;
$stripStr .= $tokens[$i][1];
}
}
}
return $stripStr;
}
//[RUNTIME]
// 编译文件
function compile($filename) {
$content = file_get_contents($filename);
// 替换预编译指令
$content = preg_replace('/\/\/\[RUNTIME\](.*?)\/\/\[\/RUNTIME\]/s', '', $content);
$content = substr(trim($content), 5);
if ('?>' == substr($content, -2))
$content = substr($content, 0, -2);
return $content;
}
// 根据数组生成常量定义
function array_define($array,$check=true) {
$content = "\n";
foreach ($array as $key => $val) {
$key = strtoupper($key);
if($check) $content .= 'defined(\'' . $key . '\') or ';
if (is_int($val) || is_float($val)) {
$content .= "define('" . $key . "'," . $val . ');';
} elseif (is_bool($val)) {
$val = ($val) ? 'true' : 'false';
$content .= "define('" . $key . "'," . $val . ');';
} elseif (is_string($val)) {
$content .= "define('" . $key . "','" . addslashes($val) . "');";
}
$content .= "\n";
}
return $content;
}
//[/RUNTIME]
/**
* 添加和获取页面Trace记录
* @param string $value 变量
* @param string $label 标签
* @param string $level 日志级别
* @param boolean $record 是否记录日志
* @return void
*/
function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
static $_trace = array();
if('[think]' === $value){ // 获取trace信息
return $_trace;
}else{
$info = ($label?$label.':':'').print_r($value,true);
if('ERR' == $level && C('TRACE_EXCEPTION')) {// 抛出异常
throw_exception($info);
}
$level = strtoupper($level);
if(!isset($_trace[$level])) {
$_trace[$level] = array();
}
$_trace[$level][] = $info;
if((defined('IS_AJAX') && IS_AJAX) || !C('SHOW_PAGE_TRACE') || $record) {
Log::record($info,$level,$record);
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Think 标准模式公共函数库
* @category Think
* @package Common
* @author liu21st <liu21st@gmail.com>
*/
/**
* 错误输出
* @param mixed $error 错误
* @return void
*/
function halt($error) {
$e = array();
if (APP_DEBUG) {
//调试模式下输出错误信息
if (!is_array($error)) {
$trace = debug_backtrace();
$e['message'] = $error;
$e['file'] = $trace[0]['file'];
$e['line'] = $trace[0]['line'];
ob_start();
debug_print_backtrace();
$e['trace'] = ob_get_clean();
} else {
$e = $error;
}
} else {
//否则定向到错误页面
$error_page = C('ERROR_PAGE');
if (!empty($error_page)) {
redirect($error_page);
} else {
if (C('SHOW_ERROR_MSG'))
$e['message'] = is_array($error) ? $error['message'] : $error;
else
$e['message'] = C('ERROR_MESSAGE');
}
}
// 包含异常页面模板
include C('TMPL_EXCEPTION_FILE');
exit;
}
/**
* 自定义异常处理
* @param string $msg 异常消息
* @param string $type 异常类型 默认为ThinkException
* @param integer $code 异常代码 默认为0
* @return void
*/
function throw_exception($msg, $type='ThinkException', $code=0) {
if (class_exists($type, false))
throw new $type($msg, $code);
else
halt($msg); // 异常类型不存在则输出错误信息字串
}
/**
* 浏览器友好的变量输出
* @param mixed $var 变量
* @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
* @param string $label 标签 默认为空
* @param boolean $strict 是否严谨 默认为true
* @return void|string
*/
function dump($var, $echo=true, $label=null, $strict=true) {
$label = ($label === null) ? '' : rtrim($label) . ' ';
if (!$strict) {
if (ini_get('html_errors')) {
$output = print_r($var, true);
$output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
} else {
$output = $label . print_r($var, true);
}
} else {
ob_start();
var_dump($var);
$output = ob_get_clean();
if (!extension_loaded('xdebug')) {
$output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
$output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
}
}
if ($echo) {
echo($output);
return null;
}else
return $output;
}
/**
* 404处理
* 调试模式会抛异常
* 部署模式下面传入url参数可以指定跳转页面,否则发送404信息
* @param string $msg 提示信息
* @param string $url 跳转URL地址
* @return void
*/
function _404($msg='',$url='') {
APP_DEBUG && throw_exception($msg);
if($msg && C('LOG_EXCEPTION_RECORD')) Log::write($msg);
if(empty($url) && C('URL_404_REDIRECT')) {
$url = C('URL_404_REDIRECT');
}
if($url) {
redirect($url);
}else{
send_http_status(404);
exit;
}
}
/**
* 设置当前页面的布局
* @param string|false $layout 布局名称 为false的时候表示关闭布局
* @return void
*/
function layout($layout) {
if(false !== $layout) {
// 开启布局
C('LAYOUT_ON',true);
if(is_string($layout)) { // 设置新的布局模板
C('LAYOUT_NAME',$layout);
}
}else{// 临时关闭布局
C('LAYOUT_ON',false);
}
}
/**
* URL组装 支持不同URL模式
* @param string $url URL表达式,格式:'[分组/模块/操作#锚点@域名]?参数1=值1&参数2=值2...'
* @param string|array $vars 传入的参数,支持数组和字符串
* @param string $suffix 伪静态后缀,默认为true表示获取配置值
* @param boolean $redirect 是否跳转,如果设置为true则表示跳转到该URL地址
* @param boolean $domain 是否显示域名
* @return string
*/
function U($url='',$vars='',$suffix=true,$redirect=false,$domain=false) {
// 解析URL
$info = parse_url($url);
$url = !empty($info['path'])?$info['path']:ACTION_NAME;
if(isset($info['fragment'])) { // 解析锚点
$anchor = $info['fragment'];
if(false !== strpos($anchor,'?')) { // 解析参数
list($anchor,$info['query']) = explode('?',$anchor,2);
}
if(false !== strpos($anchor,'@')) { // 解析域名
list($anchor,$host) = explode('@',$anchor, 2);
}
}elseif(false !== strpos($url,'@')) { // 解析域名
list($url,$host) = explode('@',$info['path'], 2);
}
// 解析子域名
if(isset($host)) {
$domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.'));
}elseif($domain===true){
$domain = $_SERVER['HTTP_HOST'];
if(C('APP_SUB_DOMAIN_DEPLOY') ) { // 开启子域名部署
$domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.');
// '子域名'=>array('项目[/分组]');
foreach (C('APP_SUB_DOMAIN_RULES') as $key => $rule) {
if(false === strpos($key,'*') && 0=== strpos($url,$rule[0])) {
$domain = $key.strstr($domain,'.'); // 生成对应子域名
$url = substr_replace($url,'',0,strlen($rule[0]));
break;
}
}
}
}
// 解析参数
if(is_string($vars)) { // aaa=1&bbb=2 转换成数组
parse_str($vars,$vars);
}elseif(!is_array($vars)){
$vars = array();
}
if(isset($info['query'])) { // 解析地址里面参数 合并到vars
parse_str($info['query'],$params);
$vars = array_merge($params,$vars);
}
// URL组装
$depr = C('URL_PATHINFO_DEPR');
if($url) {
if(0=== strpos($url,'/')) {// 定义路由
$route = true;
$url = substr($url,1);
if('/' != $depr) {
$url = str_replace('/',$depr,$url);
}
}else{
if('/' != $depr) { // 安全替换
$url = str_replace('/',$depr,$url);
}
// 解析分组、模块和操作
$url = trim($url,$depr);
$path = explode($depr,$url);
$var = array();
$var[C('VAR_ACTION')] = !empty($path)?array_pop($path):ACTION_NAME;
$var[C('VAR_MODULE')] = !empty($path)?array_pop($path):MODULE_NAME;
if($maps = C('URL_ACTION_MAP')) {
if(isset($maps[strtolower($var[C('VAR_MODULE')])])) {
$maps = $maps[strtolower($var[C('VAR_MODULE')])];
if($action = array_search(strtolower($var[C('VAR_ACTION')]),$maps)){
$var[C('VAR_ACTION')] = $action;
}
}
}
if($maps = C('URL_MODULE_MAP')) {
if($module = array_search(strtolower($var[C('VAR_MODULE')]),$maps)){
$var[C('VAR_MODULE')] = $module;
}
}
if(C('URL_CASE_INSENSITIVE')) {
$var[C('VAR_MODULE')] = parse_name($var[C('VAR_MODULE')]);
}
if(!C('APP_SUB_DOMAIN_DEPLOY') && C('APP_GROUP_LIST')) {
if(!empty($path)) {
$group = array_pop($path);
$var[C('VAR_GROUP')] = $group;
}else{
if(GROUP_NAME != C('DEFAULT_GROUP')) {
$var[C('VAR_GROUP')]= GROUP_NAME;
}
}
if(C('URL_CASE_INSENSITIVE') && isset($var[C('VAR_GROUP')])) {
$var[C('VAR_GROUP')] = strtolower($var[C('VAR_GROUP')]);
}
}
}
}
if(C('URL_MODEL') == 0) { // 普通模式URL转换
$url = __APP__.'?'.http_build_query(array_reverse($var));
if(!empty($vars)) {
$vars = urldecode(http_build_query($vars));
$url .= '&'.$vars;
}
}else{ // PATHINFO模式或者兼容URL模式
if(isset($route)) {
$url = __APP__.'/'.rtrim($url,$depr);
}else{
$url = __APP__.'/'.implode($depr,array_reverse($var));
}
if(!empty($vars)) { // 添加参数
foreach ($vars as $var => $val){
if('' !== trim($val)) $url .= $depr . $var . $depr . urlencode($val);
}
}
if($suffix) {
$suffix = $suffix===true?C('URL_HTML_SUFFIX'):$suffix;
if($pos = strpos($suffix, '|')){
$suffix = substr($suffix, 0, $pos);
}
if($suffix && '/' != substr($url,-1)){
$url .= '.'.ltrim($suffix,'.');
}
}
}
if(isset($anchor)){
$url .= '#'.$anchor;
}
if($domain) {
$url = (is_ssl()?'https://':'http://').$domain.$url;
}
if($redirect) // 直接跳转URL
redirect($url);
else
return $url;
}
/**
* 渲染输出Widget
* @param string $name Widget名称
* @param array $data 传入的参数
* @param boolean $return 是否返回内容
* @param string $path Widget所在路径
* @return void
*/
function W($name, $data=array(), $return=false,$path='') {
$class = $name . 'Widget';
$path = empty($path) ? BASE_LIB_PATH : $path;
require_cache($path . 'Widget/' . $class . '.class.php');
if (!class_exists($class))
throw_exception(L('_CLASS_NOT_EXIST_') . ':' . $class);
$widget = Think::instance($class);
$content = $widget->render($data);
if ($return)
return $content;
else
echo $content;
}
/**
* 过滤器方法 引用传值
* @param string $name 过滤器名称
* @param string $content 要过滤的内容
* @return void
*/
function filter($name, &$content) {
$class = $name . 'Filter';
require_cache(BASE_LIB_PATH . 'Filter/' . $class . '.class.php');
$filter = new $class();
$content = $filter->run($content);
}
/**
* 判断是否SSL协议
* @return boolean
*/
function is_ssl() {
if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){
return true;
}elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
return true;
}
return false;
}
/**
* URL重定向
* @param string $url 重定向的URL地址
* @param integer $time 重定向的等待时间(秒)
* @param string $msg 重定向前的提示信息
* @return void
*/
function redirect($url, $time=0, $msg='') {
//多行URL地址支持
$url = str_replace(array("\n", "\r"), '', $url);
if (empty($msg))
$msg = "系统将在{$time}秒之后自动跳转到{$url}!";
if (!headers_sent()) {
// redirect
if (0 === $time) {
header('Location: ' . $url);
} else {
header("refresh:{$time};url={$url}");
echo($msg);
}
exit();
} else {
$str = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
if ($time != 0)
$str .= $msg;
exit($str);
}
}
/**
* 缓存管理
* @param mixed $name 缓存名称,如果为数组表示进行缓存设置
* @param mixed $value 缓存值
* @param mixed $options 缓存参数
* @return mixed
*/
function S($name,$value='',$options=null) {
static $cache = '';
if(is_array($options) && empty($cache)){
// 缓存操作的同时初始化
$type = isset($options['type'])?$options['type']:'';
$cache = Cache::getInstance($type,$options);
}elseif(is_array($name)) { // 缓存初始化
$type = isset($name['type'])?$name['type']:'';
$cache = Cache::getInstance($type,$name);
return $cache;
}elseif(empty($cache)) { // 自动初始化
$cache = Cache::getInstance();
}
if(''=== $value){ // 获取缓存
return $cache->get($name);
}elseif(is_null($value)) { // 删除缓存
return $cache->rm($name);
}else { // 缓存数据
if(is_array($options)) {
$expire = isset($options['expire'])?$options['expire']:NULL;
}else{
$expire = is_numeric($options)?$options:NULL;
}
return $cache->set($name, $value, $expire);
}
}
// S方法的别名 已经废除 不再建议使用
function cache($name,$value='',$options=null){
return S($name,$value,$options);
}
/**
* 快速文件数据读取和保存 针对简单类型数据 字符串、数组
* @param string $name 缓存名称
* @param mixed $value 缓存值
* @param string $path 缓存路径
* @return mixed
*/
function F($name, $value='', $path=DATA_PATH) {
static $_cache = array();
$filename = $path . $name . '.php';
if ('' !== $value) {
if (is_null($value)) {
// 删除缓存
return false !== strpos($name,'*')?array_map("unlink", glob($filename)):unlink($filename);
} else {
// 缓存数据
$dir = dirname($filename);
// 目录不存在则创建
if (!is_dir($dir))
mkdir($dir,0755,true);
$_cache[$name] = $value;
return file_put_contents($filename, strip_whitespace("<?php\treturn " . var_export($value, true) . ";?>"));
}
}
if (isset($_cache[$name]))
return $_cache[$name];
// 获取缓存数据
if (is_file($filename)) {
$value = include $filename;
$_cache[$name] = $value;
} else {
$value = false;
}
return $value;
}
/**
* 取得对象实例 支持调用类的静态方法
* @param string $name 类名
* @param string $method 方法名,如果为空则返回实例化对象
* @param array $args 调用参数
* @return object
*/
function get_instance_of($name, $method='', $args=array()) {
static $_instance = array();
$identify = empty($args) ? $name . $method : $name . $method . to_guid_string($args);
if (!isset($_instance[$identify])) {
if (class_exists($name)) {
$o = new $name();
if (method_exists($o, $method)) {
if (!empty($args)) {
$_instance[$identify] = call_user_func_array(array(&$o, $method), $args);
} else {
$_instance[$identify] = $o->$method();
}
}
else
$_instance[$identify] = $o;
}
else
halt(L('_CLASS_NOT_EXIST_') . ':' . $name);
}
return $_instance[$identify];
}
/**
* 根据PHP各种类型变量生成唯一标识号
* @param mixed $mix 变量
* @return string
*/
function to_guid_string($mix) {
if (is_object($mix) && function_exists('spl_object_hash')) {
return spl_object_hash($mix);
} elseif (is_resource($mix)) {
$mix = get_resource_type($mix) . strval($mix);
} else {
$mix = serialize($mix);
}
return md5($mix);
}
/**
* XML编码
* @param mixed $data 数据
* @param string $root 根节点名
* @param string $item 数字索引的子节点名
* @param string $attr 根节点属性
* @param string $id 数字索引子节点key转换的属性名
* @param string $encoding 数据编码
* @return string
*/
function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
if(is_array($attr)){
$_attr = array();
foreach ($attr as $key => $value) {
$_attr[] = "{$key}=\"{$value}\"";
}
$attr = implode(' ', $_attr);
}
$attr = trim($attr);
$attr = empty($attr) ? '' : " {$attr}";
$xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
$xml .= "<{$root}{$attr}>";
$xml .= data_to_xml($data, $item, $id);
$xml .= "</{$root}>";
return $xml;
}
/**
* 数据XML编码
* @param mixed $data 数据
* @param string $item 数字索引时的节点名称
* @param string $id 数字索引key转换为的属性名
* @return string
*/
function data_to_xml($data, $item='item', $id='id') {
$xml = $attr = '';
foreach ($data as $key => $val) {
if(is_numeric($key)){
$id && $attr = " {$id}=\"{$key}\"";
$key = $item;
}
$xml .= "<{$key}{$attr}>";
$xml .= (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
$xml .= "</{$key}>";
}
return $xml;
}
/**
* session管理函数
* @param string|array $name session名称 如果为数组则表示进行session设置
* @param mixed $value session值
* @return mixed
*/
function session($name,$value='') {
$prefix = C('SESSION_PREFIX');
if(is_array($name)) { // session初始化 在session_start 之前调用
if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
session_id($_REQUEST[C('VAR_SESSION_ID')]);
}elseif(isset($name['id'])) {
session_id($name['id']);
}
ini_set('session.auto_start', 0);
if(isset($name['name'])) session_name($name['name']);
if(isset($name['path'])) session_save_path($name['path']);
if(isset($name['domain'])) ini_set('session.cookie_domain', $name['domain']);
if(isset($name['expire'])) ini_set('session.gc_maxlifetime', $name['expire']);
if(isset($name['use_trans_sid'])) ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
if(isset($name['use_cookies'])) ini_set('session.use_cookies', $name['use_cookies']?1:0);
if(isset($name['cache_limiter'])) session_cache_limiter($name['cache_limiter']);
if(isset($name['cache_expire'])) session_cache_expire($name['cache_expire']);
if(isset($name['type'])) C('SESSION_TYPE',$name['type']);
if(C('SESSION_TYPE')) { // 读取session驱动
$class = 'Session'. ucwords(strtolower(C('SESSION_TYPE')));
// 检查驱动类
if(require_cache(EXTEND_PATH.'Driver/Session/'.$class.'.class.php')) {
$hander = new $class();
$hander->execute();
}else {
// 类没有定义
throw_exception(L('_CLASS_NOT_EXIST_').': ' . $class);
}
}
// 启动session
if(C('SESSION_AUTO_START')) session_start();
}elseif('' === $value){
if(0===strpos($name,'[')) { // session 操作
if('[pause]'==$name){ // 暂停session
session_write_close();
}elseif('[start]'==$name){ // 启动session
session_start();
}elseif('[destroy]'==$name){ // 销毁session
$_SESSION = array();
session_unset();
session_destroy();
}elseif('[regenerate]'==$name){ // 重新生成id
session_regenerate_id();
}
}elseif(0===strpos($name,'?')){ // 检查session
$name = substr($name,1);
if(strpos($name,'.')){ // 支持数组
list($name1,$name2) = explode('.',$name);
return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
}else{
return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
}
}elseif(is_null($name)){ // 清空session
if($prefix) {
unset($_SESSION[$prefix]);
}else{
$_SESSION = array();
}
}elseif($prefix){ // 获取session
if(strpos($name,'.')){
list($name1,$name2) = explode('.',$name);
return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;
}else{
return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;
}
}else{
if(strpos($name,'.')){
list($name1,$name2) = explode('.',$name);
return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;
}else{
return isset($_SESSION[$name])?$_SESSION[$name]:null;
}
}
}elseif(is_null($value)){ // 删除session
if($prefix){
unset($_SESSION[$prefix][$name]);
}else{
unset($_SESSION[$name]);
}
}else{ // 设置session
if($prefix){
if (!is_array($_SESSION[$prefix])) {
$_SESSION[$prefix] = array();
}
$_SESSION[$prefix][$name] = $value;
}else{
$_SESSION[$name] = $value;
}
}
}
/**
* Cookie 设置、获取、删除
* @param string $name cookie名称
* @param mixed $value cookie值
* @param mixed $options cookie参数
* @return mixed
*/
function cookie($name, $value='', $option=null) {
// 默认设置
$config = array(
'prefix' => C('COOKIE_PREFIX'), // cookie 名称前缀
'expire' => C('COOKIE_EXPIRE'), // cookie 保存时间
'path' => C('COOKIE_PATH'), // cookie 保存路径
'domain' => C('COOKIE_DOMAIN'), // cookie 有效域名
);
// 参数设置(会覆盖黙认设置)
if (!is_null($option)) {
if (is_numeric($option))
$option = array('expire' => $option);
elseif (is_string($option))
parse_str($option, $option);
$config = array_merge($config, array_change_key_case($option));
}
// 清除指定前缀的所有cookie
if (is_null($name)) {
if (empty($_COOKIE))
return;
// 要删除的cookie前缀,不指定则删除config设置的指定前缀
$prefix = empty($value) ? $config['prefix'] : $value;
if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
foreach ($_COOKIE as $key => $val) {
if (0 === stripos($key, $prefix)) {
setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
unset($_COOKIE[$key]);
}
}
}
return;
}
$name = $config['prefix'] . $name;
if ('' === $value) {
if(isset($_COOKIE[$name])){
$value = $_COOKIE[$name];
if(0===strpos($value,'think:')){
$value = substr($value,6);
return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
}else{
return $value;
}
}else{
return null;
}
} else {
if (is_null($value)) {
setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
unset($_COOKIE[$name]); // 删除指定cookie
} else {
// 设置cookie
if(is_array($value)){
$value = 'think:'.json_encode(array_map('urlencode',$value));
}
$expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
setcookie($name, $value, $expire, $config['path'], $config['domain']);
$_COOKIE[$name] = $value;
}
}
}
/**
* 加载动态扩展文件
* @return void
*/
function load_ext_file() {
// 加载自定义外部文件
if(C('LOAD_EXT_FILE')) {
$files = explode(',',C('LOAD_EXT_FILE'));
foreach ($files as $file){
$file = COMMON_PATH.$file.'.php';
if(is_file($file)) include $file;
}
}
// 加载自定义的动态配置文件
if(C('LOAD_EXT_CONFIG')) {
$configs = C('LOAD_EXT_CONFIG');
if(is_string($configs)) $configs = explode(',',$configs);
foreach ($configs as $key=>$config){
$file = CONF_PATH.$config.'.php';
if(is_file($file)) {
is_numeric($key)?C(include $file):C($key,include $file);
}
}
}
}
/**
* 获取客户端IP地址
* @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
* @return mixed
*/
function get_client_ip($type = 0) {
$type = $type ? 1 : 0;
static $ip = NULL;
if ($ip !== NULL) return $ip[$type];
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$pos = array_search('unknown',$arr);
if(false !== $pos) unset($arr[$pos]);
$ip = trim($arr[0]);
}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
}elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// IP地址合法验证
$long = sprintf("%u",ip2long($ip));
$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
return $ip[$type];
}
/**
* 发送HTTP状态
* @param integer $code 状态码
* @return void
*/
function send_http_status($code) {
static $_status = array(
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
// Success 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Moved Temporarily ', // 1.1
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
// 306 is deprecated but reserved
307 => 'Temporary Redirect',
// Client Error 4xx
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
509 => 'Bandwidth Limit Exceeded'
);
if(isset($_status[$code])) {
header('HTTP/1.1 '.$code.' '.$_status[$code]);
// 确保FastCGI模式下正常
header('Status:'.$code.' '.$_status[$code]);
}
}
// 过滤表单中的表达式
function filter_exp(&$value){
if (in_array(strtolower($value),array('exp','or'))){
$value .= ' ';
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP 运行时文件 编译后不再加载
* @category Think
* @package Common
* @author liu21st <liu21st@gmail.com>
*/
defined('THINK_PATH') or exit();
if(version_compare(PHP_VERSION,'5.2.0','<')) die('require PHP > 5.2.0 !');
// 版本信息
define('THINK_VERSION', '3.1.3');
// 系统信息
if(version_compare(PHP_VERSION,'5.4.0','<')) {
ini_set('magic_quotes_runtime',0);
define('MAGIC_QUOTES_GPC',get_magic_quotes_gpc()?True:False);
}else{
define('MAGIC_QUOTES_GPC',false);
}
define('IS_CGI',substr(PHP_SAPI, 0,3)=='cgi' ? 1 : 0 );
define('IS_WIN',strstr(PHP_OS, 'WIN') ? 1 : 0 );
define('IS_CLI',PHP_SAPI=='cli'? 1 : 0);
// 项目名称
defined('APP_NAME') or define('APP_NAME', basename(dirname($_SERVER['SCRIPT_FILENAME'])));
if(!IS_CLI) {
// 当前文件名
if(!defined('_PHP_FILE_')) {
if(IS_CGI) {
//CGI/FASTCGI模式下
$_temp = explode('.php',$_SERVER['PHP_SELF']);
define('_PHP_FILE_', rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/'));
}else {
define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'],'/'));
}
}
if(!defined('__ROOT__')) {
// 网站URL根目录
if( strtoupper(APP_NAME) == strtoupper(basename(dirname(_PHP_FILE_))) ) {
$_root = dirname(dirname(_PHP_FILE_));
}else {
$_root = dirname(_PHP_FILE_);
}
define('__ROOT__', (($_root=='/' || $_root=='\\')?'':$_root));
}
//支持的URL模式
define('URL_COMMON', 0); //普通模式
define('URL_PATHINFO', 1); //PATHINFO模式
define('URL_REWRITE', 2); //REWRITE模式
define('URL_COMPAT', 3); // 兼容模式
}
// 路径设置 可在入口文件中重新定义 所有路径常量都必须以/ 结尾
defined('CORE_PATH') or define('CORE_PATH', THINK_PATH.'Lib/'); // 系统核心类库目录
defined('EXTEND_PATH') or define('EXTEND_PATH', THINK_PATH.'Extend/'); // 系统扩展目录
defined('MODE_PATH') or define('MODE_PATH', EXTEND_PATH.'Mode/'); // 模式扩展目录
defined('ENGINE_PATH') or define('ENGINE_PATH', EXTEND_PATH.'Engine/'); // 引擎扩展目录
defined('VENDOR_PATH') or define('VENDOR_PATH', EXTEND_PATH.'Vendor/'); // 第三方类库目录
defined('LIBRARY_PATH') or define('LIBRARY_PATH', EXTEND_PATH.'Library/'); // 扩展类库目录
defined('COMMON_PATH') or define('COMMON_PATH', APP_PATH.'Common/'); // 项目公共目录
defined('LIB_PATH') or define('LIB_PATH', APP_PATH.'Lib/'); // 项目类库目录
defined('CONF_PATH') or define('CONF_PATH', APP_PATH.'Conf/'); // 项目配置目录
defined('LANG_PATH') or define('LANG_PATH', APP_PATH.'Lang/'); // 项目语言包目录
defined('TMPL_PATH') or define('TMPL_PATH', APP_PATH.'Tpl/'); // 项目模板目录
defined('HTML_PATH') or define('HTML_PATH', APP_PATH.'Html/'); // 项目静态目录
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH.'Logs/'); // 项目日志目录
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH.'Temp/'); // 项目缓存目录
defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH.'Data/'); // 项目数据目录
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH.'Cache/'); // 项目模板缓存目录
// 为了方便导入第三方类库 设置Vendor目录到include_path
set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH);
// 加载运行时所需要的文件 并负责自动目录生成
function load_runtime_file() {
// 加载系统基础函数库
require THINK_PATH.'Common/common.php';
// 读取核心文件列表
$list = array(
CORE_PATH.'Core/Think.class.php',
CORE_PATH.'Core/ThinkException.class.php', // 异常处理类
CORE_PATH.'Core/Behavior.class.php',
);
// 加载模式文件列表
foreach ($list as $key=>$file){
if(is_file($file)) require_cache($file);
}
// 加载系统类库别名定义
alias_import(include THINK_PATH.'Conf/alias.php');
// 检查项目目录结构 如果不存在则自动创建
if(!is_dir(LIB_PATH)) {
// 创建项目目录结构
build_app_dir();
}elseif(!is_dir(CACHE_PATH)){
// 检查缓存目录
check_runtime();
}elseif(APP_DEBUG){
// 调试模式切换删除编译缓存
if(is_file(RUNTIME_FILE)) unlink(RUNTIME_FILE);
}
}
// 检查缓存目录(Runtime) 如果不存在则自动创建
function check_runtime() {
if(!is_dir(RUNTIME_PATH)) {
mkdir(RUNTIME_PATH);
}elseif(!is_writeable(RUNTIME_PATH)) {
header('Content-Type:text/html; charset=utf-8');
exit('目录 [ '.RUNTIME_PATH.' ] 不可写!');
}
mkdir(CACHE_PATH); // 模板缓存目录
if(!is_dir(LOG_PATH)) mkdir(LOG_PATH); // 日志目录
if(!is_dir(TEMP_PATH)) mkdir(TEMP_PATH); // 数据缓存目录
if(!is_dir(DATA_PATH)) mkdir(DATA_PATH); // 数据文件目录
return true;
}
// 创建编译缓存
function build_runtime_cache($append='') {
// 生成编译文件
$defs = get_defined_constants(TRUE);
$content = '$GLOBALS[\'_beginTime\'] = microtime(TRUE);';
if(defined('RUNTIME_DEF_FILE')) { // 编译后的常量文件外部引入
file_put_contents(RUNTIME_DEF_FILE,'<?php '.array_define($defs['user']));
$content .= 'require \''.RUNTIME_DEF_FILE.'\';';
}else{
$content .= array_define($defs['user']);
}
$content .= 'set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH);';
// 读取核心编译文件列表
$list = array(
THINK_PATH.'Common/common.php',
CORE_PATH.'Core/Think.class.php',
CORE_PATH.'Core/ThinkException.class.php',
CORE_PATH.'Core/Behavior.class.php',
);
foreach ($list as $file){
$content .= compile($file);
}
// 系统行为扩展文件统一编译
$content .= build_tags_cache();
$alias = include THINK_PATH.'Conf/alias.php';
$content .= 'alias_import('.var_export($alias,true).');';
// 编译框架默认语言包和配置参数
$content .= $append."\nL(".var_export(L(),true).");C(".var_export(C(),true).');G(\'loadTime\');Think::Start();';
file_put_contents(RUNTIME_FILE,strip_whitespace('<?php '.str_replace("defined('THINK_PATH') or exit();",' ',$content)));
}
// 编译系统行为扩展类库
function build_tags_cache() {
$tags = C('extends');
$content = '';
foreach ($tags as $tag=>$item){
foreach ($item as $key=>$name) {
$content .= is_int($key)?compile(CORE_PATH.'Behavior/'.$name.'Behavior.class.php'):compile($name);
}
}
return $content;
}
// 创建项目目录结构
function build_app_dir() {
// 没有创建项目目录的话自动创建
if(!is_dir(APP_PATH)) mkdir(APP_PATH,0755,true);
if(is_writeable(APP_PATH)) {
$dirs = array(
LIB_PATH,
RUNTIME_PATH,
CONF_PATH,
COMMON_PATH,
LANG_PATH,
CACHE_PATH,
TMPL_PATH,
TMPL_PATH.C('DEFAULT_THEME').'/',
LOG_PATH,
TEMP_PATH,
DATA_PATH,
LIB_PATH.'Model/',
LIB_PATH.'Action/',
LIB_PATH.'Behavior/',
LIB_PATH.'Widget/',
);
foreach ($dirs as $dir){
if(!is_dir($dir)) mkdir($dir,0755,true);
}
// 写入目录安全文件
build_dir_secure($dirs);
// 写入初始配置文件
if(!is_file(CONF_PATH.'config.php'))
file_put_contents(CONF_PATH.'config.php',"<?php\nreturn array(\n\t//'配置项'=>'配置值'\n);\n?>");
// 写入测试Action
if(!is_file(LIB_PATH.'Action/IndexAction.class.php'))
build_first_action();
}else{
header('Content-Type:text/html; charset=utf-8');
exit('项目目录不可写,目录无法自动生成!<BR>请使用项目生成器或者手动生成项目目录~');
}
}
// 创建测试Action
function build_first_action() {
$content = file_get_contents(THINK_PATH.'Tpl/default_index.tpl');
file_put_contents(LIB_PATH.'Action/IndexAction.class.php',$content);
}
// 生成目录安全文件
function build_dir_secure($dirs=array()) {
// 目录安全写入
if(defined('BUILD_DIR_SECURE') && BUILD_DIR_SECURE) {
defined('DIR_SECURE_FILENAME') or define('DIR_SECURE_FILENAME', 'index.html');
defined('DIR_SECURE_CONTENT') or define('DIR_SECURE_CONTENT', ' ');
// 自动写入目录安全文件
$content = DIR_SECURE_CONTENT;
$files = explode(',', DIR_SECURE_FILENAME);
foreach ($files as $filename){
foreach ($dirs as $dir)
file_put_contents($dir.$filename,$content);
}
}
}
// 加载运行时所需文件
load_runtime_file();
// 记录加载文件时间
G('loadTime');
// 执行入口
Think::Start();
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
// 系统别名定义文件
return array(
'Model' => CORE_PATH.'Core/Model.class.php',
'Db' => CORE_PATH.'Core/Db.class.php',
'Log' => CORE_PATH.'Core/Log.class.php',
'ThinkTemplate' => CORE_PATH.'Template/ThinkTemplate.class.php',
'TagLib' => CORE_PATH.'Template/TagLib.class.php',
'Cache' => CORE_PATH.'Core/Cache.class.php',
'Widget' => CORE_PATH.'Core/Widget.class.php',
'TagLibCx' => CORE_PATH.'Driver/TagLib/TagLibCx.class.php',
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP惯例配置文件
* 该文件请不要修改,如果要覆盖惯例配置的值,可在项目配置文件中设定和惯例不符的配置项
* 配置名称大小写任意,系统会统一转换成小写
* 所有配置参数都可以在生效前动态改变
* @category Think
* @package Common
* @author liu21st <liu21st@gmail.com>
* @version $Id: convention.php 3088 2012-07-29 09:12:19Z luofei614@gmail.com $
*/
defined('THINK_PATH') or exit();
return array(
/* 项目设定 */
'APP_STATUS' => 'debug', // 应用调试模式状态 调试模式开启后有效 默认为debug 可扩展 并自动加载对应的配置文件
'APP_FILE_CASE' => false, // 是否检查文件的大小写 对Windows平台有效
'APP_AUTOLOAD_PATH' => '',// 自动加载机制的自动搜索路径,注意搜索顺序
'APP_TAGS_ON' => true, // 系统标签扩展开关
'APP_SUB_DOMAIN_DEPLOY' => false, // 是否开启子域名部署
'APP_SUB_DOMAIN_RULES' => array(), // 子域名部署规则
'APP_SUB_DOMAIN_DENY' => array(), // 子域名禁用列表
'APP_GROUP_LIST' => '', // 项目分组设定,多个组之间用逗号分隔,例如'Home,Admin'
'APP_GROUP_MODE' => 0, // 分组模式 0 普通分组 1 独立分组
'APP_GROUP_PATH' => 'Modules', // 分组目录 独立分组模式下面有效
'ACTION_SUFFIX' => '', // 操作方法后缀
/* Cookie设置 */
'COOKIE_EXPIRE' => 0, // Coodie有效期
'COOKIE_DOMAIN' => '', // Cookie有效域名
'COOKIE_PATH' => '/', // Cookie路径
'COOKIE_PREFIX' => '', // Cookie前缀 避免冲突
/* 默认设定 */
'DEFAULT_M_LAYER' => 'Model', // 默认的模型层名称
'DEFAULT_C_LAYER' => 'Action', // 默认的控制器层名称
'DEFAULT_V_LAYER' => 'Tpl', // 默认的视图层名称
'DEFAULT_APP' => '@', // 默认项目名称,@表示当前项目
'DEFAULT_LANG' => 'zh-cn', // 默认语言
'DEFAULT_THEME' => '', // 默认模板主题名称
'DEFAULT_GROUP' => 'Home', // 默认分组
'DEFAULT_MODULE' => 'Index', // 默认模块名称
'DEFAULT_ACTION' => 'index', // 默认操作名称
'DEFAULT_CHARSET' => 'utf-8', // 默认输出编码
'DEFAULT_TIMEZONE' => 'PRC', // 默认时区
'DEFAULT_AJAX_RETURN' => 'JSON', // 默认AJAX 数据返回格式,可选JSON XML ...
'DEFAULT_JSONP_HANDLER' => 'jsonpReturn', // 默认JSONP格式返回的处理方法
'DEFAULT_FILTER' => 'htmlspecialchars', // 默认参数过滤方法 用于 $this->_get('变量名');$this->_post('变量名')...
/* 数据库设置 */
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => 'localhost', // 服务器地址
'DB_NAME' => '', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => '', // 密码
'DB_PORT' => '', // 端口
'DB_PREFIX' => 'think_', // 数据库表前缀
'DB_FIELDTYPE_CHECK' => false, // 是否进行字段类型检查
'DB_FIELDS_CACHE' => true, // 启用字段缓存
'DB_CHARSET' => 'utf8', // 数据库编码默认采用utf8
'DB_DEPLOY_TYPE' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'DB_RW_SEPARATE' => false, // 数据库读写是否分离 主从式有效
'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量
'DB_SLAVE_NO' => '', // 指定从服务器序号
'DB_SQL_BUILD_CACHE' => false, // 数据库查询的SQL创建缓存
'DB_SQL_BUILD_QUEUE' => 'file', // SQL缓存队列的缓存方式 支持 file xcache和apc
'DB_SQL_BUILD_LENGTH' => 20, // SQL缓存的队列长度
'DB_SQL_LOG' => false, // SQL执行日志记录
/* 数据缓存设置 */
'DATA_CACHE_TIME' => 0, // 数据缓存有效期 0表示永久缓存
'DATA_CACHE_COMPRESS' => false, // 数据缓存是否压缩缓存
'DATA_CACHE_CHECK' => false, // 数据缓存是否校验缓存
'DATA_CACHE_PREFIX' => '', // 缓存前缀
'DATA_CACHE_TYPE' => 'File', // 数据缓存类型,支持:File|Db|Apc|Memcache|Shmop|Sqlite|Xcache|Apachenote|Eaccelerator
'DATA_CACHE_PATH' => TEMP_PATH,// 缓存路径设置 (仅对File方式缓存有效)
'DATA_CACHE_SUBDIR' => false, // 使用子目录缓存 (自动根据缓存标识的哈希创建子目录)
'DATA_PATH_LEVEL' => 1, // 子目录缓存级别
/* 错误设置 */
'ERROR_MESSAGE' => '页面错误!请稍后再试~',//错误显示信息,非调试模式有效
'ERROR_PAGE' => '', // 错误定向页面
'SHOW_ERROR_MSG' => false, // 显示错误信息
'TRACE_EXCEPTION' => false, // TRACE错误信息是否抛异常 针对trace方法
/* 日志设置 */
'LOG_RECORD' => false, // 默认不记录日志
'LOG_TYPE' => 3, // 日志记录类型 0 系统 1 邮件 3 文件 4 SAPI 默认为文件方式
'LOG_DEST' => '', // 日志记录目标
'LOG_EXTRA' => '', // 日志记录额外信息
'LOG_LEVEL' => 'EMERG,ALERT,CRIT,ERR',// 允许记录的日志级别
'LOG_FILE_SIZE' => 2097152, // 日志文件大小限制
'LOG_EXCEPTION_RECORD' => false, // 是否记录异常信息日志
/* SESSION设置 */
'SESSION_AUTO_START' => true, // 是否自动开启Session
'SESSION_OPTIONS' => array(), // session 配置数组 支持type name id path expire domain 等参数
'SESSION_TYPE' => '', // session hander类型 默认无需设置 除非扩展了session hander驱动
'SESSION_PREFIX' => '', // session 前缀
//'VAR_SESSION_ID' => 'session_id', //sessionID的提交变量
/* 模板引擎设置 */
'TMPL_CONTENT_TYPE' => 'text/html', // 默认模板输出类型
'TMPL_ACTION_ERROR' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认错误跳转对应的模板文件
'TMPL_ACTION_SUCCESS' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认成功跳转对应的模板文件
'TMPL_EXCEPTION_FILE' => THINK_PATH.'Tpl/think_exception.tpl',// 异常页面的模板文件
'TMPL_DETECT_THEME' => false, // 自动侦测模板主题
'TMPL_TEMPLATE_SUFFIX' => '.html', // 默认模板文件后缀
'TMPL_FILE_DEPR' => '/', //模板文件MODULE_NAME与ACTION_NAME之间的分割符
/* URL设置 */
'URL_CASE_INSENSITIVE' => false, // 默认false 表示URL区分大小写 true则表示不区分大小写
'URL_MODEL' => 1, // URL访问模式,可选参数0、1、2、3,代表以下四种模式:
// 0 (普通模式); 1 (PATHINFO 模式); 2 (REWRITE 模式); 3 (兼容模式) 默认为PATHINFO 模式,提供最好的用户体验和SEO支持
'URL_PATHINFO_DEPR' => '/', // PATHINFO模式下,各参数之间的分割符号
'URL_PATHINFO_FETCH' => 'ORIG_PATH_INFO,REDIRECT_PATH_INFO,REDIRECT_URL', // 用于兼容判断PATH_INFO 参数的SERVER替代变量列表
'URL_HTML_SUFFIX' => 'html', // URL伪静态后缀设置
'URL_DENY_SUFFIX' => 'ico|png|gif|jpg', // URL禁止访问的后缀设置
'URL_PARAMS_BIND' => true, // URL变量绑定到Action方法参数
'URL_404_REDIRECT' => '', // 404 跳转页面 部署模式有效
/* 系统变量名称设置 */
'VAR_GROUP' => 'g', // 默认分组获取变量
'VAR_MODULE' => 'm', // 默认模块获取变量
'VAR_ACTION' => 'a', // 默认操作获取变量
'VAR_AJAX_SUBMIT' => 'ajax', // 默认的AJAX提交变量
'VAR_JSONP_HANDLER' => 'callback',
'VAR_PATHINFO' => 's', // PATHINFO 兼容模式获取变量例如 ?s=/module/action/id/1 后面的参数取决于URL_PATHINFO_DEPR
'VAR_URL_PARAMS' => '_URL_', // PATHINFO URL参数变量
'VAR_TEMPLATE' => 't', // 默认模板切换变量
'VAR_FILTERS' => 'filter_exp', // 全局系统变量的默认过滤方法 多个用逗号分割
'OUTPUT_ENCODE' => false, // 页面压缩输出
'HTTP_CACHE_CONTROL' => 'private', // 网页缓存控制
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP 默认的调试模式配置文件
* 如果项目有定义自己的调试模式配置文件,本文件无效
* @category Think
* @package Common
* @author liu21st <liu21st@gmail.com>
* @version $Id: debug.php 3071 2012-07-15 07:59:23Z liu21st@gmail.com $
*/
defined('THINK_PATH') or exit();
// 调试模式下面默认设置 可以在项目配置目录下重新定义 debug.php 覆盖
return array(
'LOG_RECORD' => true, // 进行日志记录
'LOG_EXCEPTION_RECORD' => true, // 是否记录异常信息日志
'LOG_LEVEL' => 'EMERG,ALERT,CRIT,ERR,WARN,NOTIC,INFO,DEBUG,SQL', // 允许记录的日志级别
'DB_FIELDS_CACHE' => false, // 字段缓存信息
'DB_SQL_LOG' => true, // 记录SQL信息
'APP_FILE_CASE' => true, // 是否检查文件的大小写 对Windows平台有效
'TMPL_CACHE_ON' => false, // 是否开启模板编译缓存,设为false则每次都会重新编译
'TMPL_STRIP_SPACE' => false, // 是否去除模板文件里面的html空格与换行
'SHOW_ERROR_MSG' => true, // 显示错误信息
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 系统默认的核心行为扩展列表文件
return array(
'app_init' => array(
),
'app_begin' => array(
'ReadHtmlCache', // 读取静态缓存
),
'route_check' => array(
'CheckRoute', // 路由检测
),
'app_end' => array(),
'path_info' => array(),
'action_begin' => array(),
'action_end' => array(),
'view_begin' => array(),
'view_parse' => array(
'ParseTemplate', // 模板解析 支持PHP、内置模板引擎和第三方模板引擎
),
'view_filter' => array(
'ContentReplace', // 模板输出替换
'TokenBuild', // 表单令牌
'WriteHtmlCache', // 写入静态缓存
'ShowRuntime', // 运行时间显示
),
'view_end' => array(
'ShowPageTrace', // 页面Trace显示
),
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* ThinkPHP Restful 控制器扩展
* @category Extend
* @package Extend
* @subpackage Action
* @author liu21st <liu21st@gmail.com>
*/
abstract class RestAction {
// 当前Action名称
private $name = '';
// 视图实例
protected $view = null;
protected $_method = ''; // 当前请求类型
protected $_type = ''; // 当前资源类型
// 输出类型
protected $_types = array();
/**
* 架构函数 取得模板对象实例
* @access public
*/
public function __construct() {
//实例化视图类
$this->view = Think::instance('View');
if(!defined('__EXT__')) define('__EXT__','');
// 资源类型检测
if(''==__EXT__) { // 自动检测资源类型
$this->_type = $this->getAcceptType();
}elseif(false === stripos(C('REST_CONTENT_TYPE_LIST'),__EXT__)) {
// 资源类型非法 则用默认资源类型访问
$this->_type = C('REST_DEFAULT_TYPE');
}else{
// 检测实际资源类型
if($this->getAcceptType() == __EXT__) {
$this->_type = __EXT__;
}else{
$this->_type = C('REST_DEFAULT_TYPE');
}
}
// 请求方式检测
$method = strtolower($_SERVER['REQUEST_METHOD']);
if(false === stripos(C('REST_METHOD_LIST'),$method)) {
// 请求方式非法 则用默认请求方法
$method = C('REST_DEFAULT_METHOD');
}
$this->_method = $method;
// 允许输出的资源类型
$this->_types = C('REST_OUTPUT_TYPE');
//控制器初始化
if(method_exists($this,'_initialize'))
$this->_initialize();
}
/**
* 获取当前Action名称
* @access protected
*/
protected function getActionName() {
if(empty($this->name)) {
// 获取Action名称
$this->name = substr(get_class($this),0,-6);
}
return $this->name;
}
/**
* 是否AJAX请求
* @access protected
* @return boolean
*/
protected function isAjax() {
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) ) {
if('xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH']))
return true;
}
if(!empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')]))
// 判断Ajax方式提交
return true;
return false;
}
/**
* 魔术方法 有不存在的操作的时候执行
* @access public
* @param string $method 方法名
* @param array $args 参数
* @return mixed
*/
public function __call($method,$args) {
if( 0 === strcasecmp($method,ACTION_NAME)) {
if(method_exists($this,$method.'_'.$this->_method.'_'.$this->_type)) { // RESTFul方法支持
$fun = $method.'_'.$this->_method.'_'.$this->_type;
$this->$fun();
}elseif($this->_method == C('REST_DEFAULT_METHOD') && method_exists($this,$method.'_'.$this->_type) ){
$fun = $method.'_'.$this->_type;
$this->$fun();
}elseif($this->_type == C('REST_DEFAULT_TYPE') && method_exists($this,$method.'_'.$this->_method) ){
$fun = $method.'_'.$this->_method;
$this->$fun();
}elseif(method_exists($this,'_empty')) {
// 如果定义了_empty操作 则调用
$this->_empty($method,$args);
}elseif(file_exists_case(C('TMPL_FILE_NAME'))){
// 检查是否存在默认模版 如果有直接输出模版
$this->display();
}else{
// 抛出异常
throw_exception(L('_ERROR_ACTION_').ACTION_NAME);
}
}else{
switch(strtolower($method)) {
// 获取变量 支持过滤和默认值 调用方式 $this->_post($key,$filter,$default);
case '_get': $input =& $_GET;break;
case '_post':$input =& $_POST;break;
case '_put':
case '_delete':parse_str(file_get_contents('php://input'), $input);break;
case '_request': $input =& $_REQUEST;break;
case '_session': $input =& $_SESSION;break;
case '_cookie': $input =& $_COOKIE;break;
case '_server': $input =& $_SERVER;break;
default:
throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_'));
}
if(isset($input[$args[0]])) { // 取值操作
$data = $input[$args[0]];
$fun = $args[1]?$args[1]:C('DEFAULT_FILTER');
$data = $fun($data); // 参数过滤
}else{ // 变量默认值
$data = isset($args[2])?$args[2]:NULL;
}
return $data;
}
}
/**
* 模板显示
* 调用内置的模板引擎显示方法,
* @access protected
* @param string $templateFile 指定要调用的模板文件
* 默认为空 由系统自动定位模板文件
* @param string $charset 输出编码
* @param string $contentType 输出类型
* @return void
*/
protected function display($templateFile='',$charset='',$contentType='') {
$this->view->display($templateFile,$charset,$contentType);
}
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return void
*/
protected function assign($name,$value='') {
$this->view->assign($name,$value);
}
public function __set($name,$value) {
$this->view->assign($name,$value);
}
/**
* 设置页面输出的CONTENT_TYPE和编码
* @access public
* @param string $type content_type 类型对应的扩展名
* @param string $charset 页面输出编码
* @return void
*/
public function setContentType($type, $charset=''){
if(headers_sent()) return;
if(empty($charset)) $charset = C('DEFAULT_CHARSET');
$type = strtolower($type);
if(isset($this->_types[$type])) //过滤content_type
header('Content-Type: '.$this->_types[$type].'; charset='.$charset);
}
/**
* 输出返回数据
* @access protected
* @param mixed $data 要返回的数据
* @param String $type 返回类型 JSON XML
* @param integer $code HTTP状态
* @return void
*/
protected function response($data,$type='',$code=200) {
// 保存日志
if(C('LOG_RECORD')) Log::save();
$this->sendHttpStatus($code);
exit($this->encodeData($data,strtolower($type)));
}
/**
* 编码数据
* @access protected
* @param mixed $data 要返回的数据
* @param String $type 返回类型 JSON XML
* @return void
*/
protected function encodeData($data,$type='') {
if(empty($data)) return '';
if('json' == $type) {
// 返回JSON数据格式到客户端 包含状态信息
$data = json_encode($data);
}elseif('xml' == $type){
// 返回xml格式数据
$data = xml_encode($data);
}elseif('php'==$type){
$data = serialize($data);
}// 默认直接输出
$this->setContentType($type);
header('Content-Length: ' . strlen($data));
return $data;
}
// 发送Http状态信息
protected function sendHttpStatus($status) {
static $_status = array(
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
// Success 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Moved Temporarily ', // 1.1
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
// 306 is deprecated but reserved
307 => 'Temporary Redirect',
// Client Error 4xx
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
509 => 'Bandwidth Limit Exceeded'
);
if(isset($_status[$code])) {
header('HTTP/1.1 '.$code.' '.$_status[$code]);
// 确保FastCGI模式下正常
header('Status:'.$code.' '.$_status[$code]);
}
}
/**
* 获取当前请求的Accept头信息
* @return string
*/
protected function getAcceptType(){
$type = array(
'html' => 'text/html,application/xhtml+xml,*/*',
'xml' => 'application/xml,text/xml,application/x-xml',
'json' => 'application/json,text/x-json,application/jsonrequest,text/json',
'js' => 'text/javascript,application/javascript,application/x-javascript',
'css' => 'text/css',
'rss' => 'application/rss+xml',
'yaml' => 'application/x-yaml,text/yaml',
'atom' => 'application/atom+xml',
'pdf' => 'application/pdf',
'text' => 'text/plain',
'png' => 'image/png',
'jpg' => 'image/jpg,image/jpeg,image/pjpeg',
'gif' => 'image/gif',
'csv' => 'text/csv'
);
foreach($type as $key=>$val){
$array = explode(',',$val);
foreach($array as $k=>$v){
if(stristr($_SERVER['HTTP_ACCEPT'], $v)) {
return $key;
}
}
}
return false;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 行为扩展:代理检测
* @category Extend
* @package Extend
* @subpackage Behavior
* @author liu21st <liu21st@gmail.com>
*/
class AgentCheckBehavior extends Behavior {
protected $options = array(
'LIMIT_PROXY_VISIT'=>true,
);
public function run(&$params) {
// 代理访问检测
if(C('LIMIT_PROXY_VISIT') && ($_SERVER['HTTP_X_FORWARDED_FOR'] || $_SERVER['HTTP_VIA'] || $_SERVER['HTTP_PROXY_CONNECTION'] || $_SERVER['HTTP_USER_AGENT_VIA'])) {
// 禁止代理访问
exit('Access Denied');
}
}
}
?>
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 浏览器防刷新检测
* @category Extend
* @package Extend
* @subpackage Behavior
* @author liu21st <liu21st@gmail.com>
*/
class BrowserCheckBehavior extends Behavior {
protected $options = array(
// 浏览器防刷新的时间间隔(秒)
'LIMIT_REFLESH_TIMES' => 10,
);
public function run(&$params) {
if($_SERVER['REQUEST_METHOD'] == 'GET') {
// 启用页面防刷新机制
$guid = md5($_SERVER['PHP_SELF']);
// 检查页面刷新间隔
if(cookie('_last_visit_time_'.$guid) && cookie('_last_visit_time_'.$guid)>time()-C('LIMIT_REFLESH_TIMES')) {
// 页面刷新读取浏览器缓存
header('HTTP/1.1 304 Not Modified');
exit;
}else{
// 缓存当前地址访问时间
cookie('_last_visit_time_'.$guid, $_SERVER['REQUEST_TIME']);
//header('Last-Modified:'.(date('D,d M Y H:i:s',$_SERVER['REQUEST_TIME']-C('LIMIT_REFLESH_TIMES'))).' GMT');
}
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 系统行为扩展:操作路由检测
* @category Think
* @package Think
* @subpackage Behavior
* @author liu21st <liu21st@gmail.com>
*/
class CheckActionRouteBehavior extends Behavior {
// 行为扩展的执行入口必须是run
public function run(&$config){
// 优先检测是否存在PATH_INFO
$regx = trim($_SERVER['PATH_INFO'],'/');
if(empty($regx)) return ;
// 路由定义文件优先于config中的配置定义
// 路由处理
$routes = $config['routes'];
if(!empty($routes)) {
$depr = C('URL_PATHINFO_DEPR');
// 分隔符替换 确保路由定义使用统一的分隔符
$regx = str_replace($depr,'/',$regx);
$regx = substr_replace($regx,'',0,strlen(__URL__));
foreach ($routes as $rule=>$route){
if(0===strpos($rule,'/') && preg_match($rule,$regx,$matches)) { // 正则路由
return C('ACTION_NAME',$this->parseRegex($matches,$route,$regx));
}else{ // 规则路由
$len1 = substr_count($regx,'/');
$len2 = substr_count($rule,'/');
if($len1>=$len2) {
if('$' == substr($rule,-1,1)) {// 完整匹配
if($len1 != $len2) {
continue;
}else{
$rule = substr($rule,0,-1);
}
}
$match = $this->checkUrlMatch($regx,$rule);
if($match) return C('ACTION_NAME',$this->parseRule($rule,$route,$regx));
}
}
}
}
}
// 检测URL和规则路由是否匹配
private function checkUrlMatch($regx,$rule) {
$m1 = explode('/',$regx);
$m2 = explode('/',$rule);
$match = true; // 是否匹配
foreach ($m2 as $key=>$val){
if(':' == substr($val,0,1)) {// 动态变量
if(strpos($val,'\\')) {
$type = substr($val,-1);
if('d'==$type && !is_numeric($m1[$key])) {
$match = false;
break;
}
}elseif(strpos($val,'^')){
$array = explode('|',substr(strstr($val,'^'),1));
if(in_array($m1[$key],$array)) {
$match = false;
break;
}
}
}elseif(0 !== strcasecmp($val,$m1[$key])){
$match = false;
break;
}
}
return $match;
}
// 解析规范的路由地址
// 地址格式 操作?参数1=值1&参数2=值2...
private function parseUrl($url) {
$var = array();
if(false !== strpos($url,'?')) { // 操作?参数1=值1&参数2=值2...
$info = parse_url($url);
$path = $info['path'];
parse_str($info['query'],$var);
}else{ // 操作
$path = $url;
}
$var[C('VAR_ACTION')] = $path;
return $var;
}
// 解析规则路由
// '路由规则'=>'操作?额外参数1=值1&额外参数2=值2...'
// '路由规则'=>array('操作','额外参数1=值1&额外参数2=值2...')
// '路由规则'=>'外部地址'
// '路由规则'=>array('外部地址','重定向代码')
// 路由规则中 :开头 表示动态变量
// 外部地址中可以用动态变量 采用 :1 :2 的方式
// 'news/:month/:day/:id'=>array('News/read?cate=1','status=1'),
// 'new/:id'=>array('/new.php?id=:1',301), 重定向
private function parseRule($rule,$route,$regx) {
// 获取路由地址规则
$url = is_array($route)?$route[0]:$route;
// 获取URL地址中的参数
$paths = explode('/',$regx);
// 解析路由规则
$matches = array();
$rule = explode('/',$rule);
foreach ($rule as $item){
if(0===strpos($item,':')) { // 动态变量获取
if($pos = strpos($item,'^') ) {
$var = substr($item,1,$pos-1);
}elseif(strpos($item,'\\')){
$var = substr($item,1,-2);
}else{
$var = substr($item,1);
}
$matches[$var] = array_shift($paths);
}else{ // 过滤URL中的静态变量
array_shift($paths);
}
}
if(0=== strpos($url,'/') || 0===strpos($url,'http')) { // 路由重定向跳转
if(strpos($url,':')) { // 传递动态参数
$values = array_values($matches);
$url = preg_replace('/:(\d+)/e','$values[\\1-1]',$url);
}
header("Location: $url", true,(is_array($route) && isset($route[1]))?$route[1]:301);
exit;
}else{
// 解析路由地址
$var = $this->parseUrl($url);
// 解析路由地址里面的动态参数
$values = array_values($matches);
foreach ($var as $key=>$val){
if(0===strpos($val,':')) {
$var[$key] = $values[substr($val,1)-1];
}
}
$var = array_merge($matches,$var);
// 解析剩余的URL参数
if($paths) {
preg_replace('@(\w+)\/([^\/]+)@e', '$var[strtolower(\'\\1\')]=strip_tags(\'\\2\');', implode('/',$paths));
}
// 解析路由自动传人参数
if(is_array($route) && isset($route[1])) {
parse_str($route[1],$params);
$var = array_merge($var,$params);
}
$action = $var[C('VAR_ACTION')];
unset($var[C('VAR_ACTION')]);
$_GET = array_merge($var,$_GET);
return $action;
}
}
// 解析正则路由
// '路由正则'=>'[分组/模块/操作]?参数1=值1&参数2=值2...'
// '路由正则'=>array('[分组/模块/操作]?参数1=值1&参数2=值2...','额外参数1=值1&额外参数2=值2...')
// '路由正则'=>'外部地址'
// '路由正则'=>array('外部地址','重定向代码')
// 参数值和外部地址中可以用动态变量 采用 :1 :2 的方式
// '/new\/(\d+)\/(\d+)/'=>array('News/read?id=:1&page=:2&cate=1','status=1'),
// '/new\/(\d+)/'=>array('/new.php?id=:1&page=:2&status=1','301'), 重定向
private function parseRegex($matches,$route,$regx) {
// 获取路由地址规则
$url = is_array($route)?$route[0]:$route;
$url = preg_replace('/:(\d+)/e','$matches[\\1]',$url);
if(0=== strpos($url,'/') || 0===strpos($url,'http')) { // 路由重定向跳转
header("Location: $url", true,(is_array($route) && isset($route[1]))?$route[1]:301);
exit;
}else{
// 解析路由地址
$var = $this->parseUrl($url);
// 解析剩余的URL参数
$regx = substr_replace($regx,'',0,strlen($matches[0]));
if($regx) {
preg_replace('@(\w+)\/([^,\/]+)@e', '$var[strtolower(\'\\1\')]=strip_tags(\'\\2\');', $regx);
}
// 解析路由自动传人参数
if(is_array($route) && isset($route[1])) {
parse_str($route[1],$params);
$var = array_merge($var,$params);
}
$action = $var[C('VAR_ACTION')];
unset($var[C('VAR_ACTION')]);
$_GET = array_merge($var,$_GET);
}
return $action;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 语言检测 并自动加载语言包
* @category Extend
* @package Extend
* @subpackage Behavior
* @author liu21st <liu21st@gmail.com>
*/
class CheckLangBehavior extends Behavior {
// 行为参数定义(默认值) 可在项目配置中覆盖
protected $options = array(
'LANG_SWITCH_ON' => false, // 默认关闭语言包功能
'LANG_AUTO_DETECT' => true, // 自动侦测语言 开启多语言功能后有效
'LANG_LIST' => 'zh-cn', // 允许切换的语言列表 用逗号分隔
'VAR_LANGUAGE' => 'l', // 默认语言切换变量
);
// 行为扩展的执行入口必须是run
public function run(&$params){
// 开启静态缓存
$this->checkLanguage();
}
/**
* 语言检查
* 检查浏览器支持语言,并自动加载语言包
* @access private
* @return void
*/
private function checkLanguage() {
// 不开启语言包功能,仅仅加载框架语言文件直接返回
if (!C('LANG_SWITCH_ON')){
return;
}
$langSet = C('DEFAULT_LANG');
// 启用了语言包功能
// 根据是否启用自动侦测设置获取语言选择
if (C('LANG_AUTO_DETECT')){
if(isset($_GET[C('VAR_LANGUAGE')])){
$langSet = $_GET[C('VAR_LANGUAGE')];// url中设置了语言变量
cookie('think_language',$langSet,3600);
}elseif(cookie('think_language')){// 获取上次用户的选择
$langSet = cookie('think_language');
}elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){// 自动侦测浏览器语言
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
$langSet = $matches[1];
cookie('think_language',$langSet,3600);
}
if(false === stripos(C('LANG_LIST'),$langSet)) { // 非法语言参数
$langSet = C('DEFAULT_LANG');
}
}
// 定义当前语言
define('LANG_SET',strtolower($langSet));
$group = '';
$path = (defined('GROUP_NAME') && C('APP_GROUP_MODE')==1) ? BASE_LIB_PATH.'Lang/'.LANG_SET.'/' : LANG_PATH.LANG_SET.'/';
// 读取项目公共语言包
if(is_file(LANG_PATH.LANG_SET.'/common.php'))
L(include LANG_PATH.LANG_SET.'/common.php');
// 读取分组公共语言包
if(defined('GROUP_NAME')){
if(C('APP_GROUP_MODE')==1){ // 独立分组
$file = $path.'common.php';
}else{ // 普通分组
$file = $path.GROUP_NAME.'.php';
$group = GROUP_NAME.C('TMPL_FILE_DEPR');
}
if(is_file($file))
L(include $file);
}
// 读取当前模块语言包
if (is_file($path.$group.strtolower(MODULE_NAME).'.php'))
L(include $path.$group.strtolower(MODULE_NAME).'.php');
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 自动执行任务
* @category Extend
* @package Extend
* @subpackage Behavior
* @author liu21st <liu21st@gmail.com>
*/
class CronRunBehavior extends Behavior {
protected $options = array(
'CRON_MAX_TIME' => 60, // 单个任务最大执行时间
);
public function run(&$params) {
// 锁定自动执行
$lockfile = RUNTIME_PATH.'cron.lock';
if(is_writable($lockfile) && filemtime($lockfile) > $_SERVER['REQUEST_TIME'] - C('CRON_MAX_TIME')) {
return ;
} else {
touch($lockfile);
}
set_time_limit(1000);
ignore_user_abort(true);
// 载入cron配置文件
// 格式 return array(
// 'cronname'=>array('filename',intervals,nextruntime),...
// );
if(is_file(RUNTIME_PATH.'~crons.php')) {
$crons = include RUNTIME_PATH.'~crons.php';
}elseif(is_file(CONF_PATH.'crons.php')){
$crons = include CONF_PATH.'crons.php';
}
if(isset($crons) && is_array($crons)) {
$update = false;
$log = array();
foreach ($crons as $key=>$cron){
if(empty($cron[2]) || $_SERVER['REQUEST_TIME']>=$cron[2]) {
// 到达时间 执行cron文件
G('cronStart');
include LIB_PATH.'Cron/'.$cron[0].'.php';
$_useTime = G('cronStart','cronEnd', 6);
// 更新cron记录
$cron[2] = $_SERVER['REQUEST_TIME']+$cron[1];
$crons[$key] = $cron;
$log[] = "Cron:$key Runat ".date('Y-m-d H:i:s')." Use $_useTime s\n";
$update = true;
}
}
if($update) {
// 记录Cron执行日志
Log::write(implode('',$log));
// 更新cron文件
$content = "<?php\nreturn ".var_export($crons,true).";\n?>";
file_put_contents(RUNTIME_PATH.'~crons.php',$content);
}
}
// 解除锁定
unlink($lockfile);
return ;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614 <weibo.com/luofei614>
// +----------------------------------------------------------------------
// $Id$
/**
+------------------------------------------------------------------------------
* 将Trace信息输出到火狐的firebug,从而不影响ajax效果和页面的布局。
+------------------------------------------------------------------------------
* 使用前,你需要先在火狐浏览器上安装firebug和firePHP两个插件。
* 定义项目的tags.php文件,
* <code>
* <?php return array(
* 'app_end'=>array(
* 'FireShowPageTrace'
* )
* );
* </code>
* 再将此文件放到项目的Behavior文件夹中即可
* 如果trace信息没有正常输出,请查看您的日志。
* firePHP,是通过http headers和firebug通讯的,所以要保证在输出trace信息之前不能有
* headers输出,你可以在入口文件第一行加入代码 ob_start(); 或者配置output_buffering
*
*/
defined('THINK_PATH') or exit();
/**
+------------------------------------------------------------------------------
* 系统行为扩展 页面Trace显示输出
+------------------------------------------------------------------------------
*/
class FireShowPageTraceBehavior extends Behavior {
// 行为参数定义
protected $options = array(
'FIRE_SHOW_PAGE_TRACE'=> true, // 显示页面Trace信息
'TRACE_PAGE_TABS'=> array('BASE'=>'基本','FILE'=>'文件','INFO'=>'流程','ERR|NOTIC'=>'错误','SQL'=>'SQL','DEBUG'=>'调试')
);
// 行为扩展的执行入口必须是run
public function run(&$params){
if(C('FIRE_SHOW_PAGE_TRACE')) $this->showTrace();
}
/**
+----------------------------------------------------------
* 显示页面Trace信息
+----------------------------------------------------------
* @access private
+----------------------------------------------------------
*/
private function showTrace() {
// 系统默认显示信息
$files = get_included_files();
$info = array();
foreach ($files as $key=>$file){
$info[] = $file.' ( '.number_format(filesize($file)/1024,2).' KB )';
}
$trace = array();
$base = array(
'请求信息'=> date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']).' '.$_SERVER['SERVER_PROTOCOL'].' '.$_SERVER['REQUEST_METHOD'].' : '.__SELF__,
'运行时间'=> $this->showTime(),
'内存开销'=> MEMORY_LIMIT_ON?number_format((memory_get_usage() - $GLOBALS['_startUseMems'])/1024,2).' kb':'不支持',
'查询信息'=> N('db_query').' queries '.N('db_write').' writes ',
'文件加载'=> count(get_included_files()),
'缓存信息'=> N('cache_read').' gets '.N('cache_write').' writes ',
'配置加载'=> count(c()),
'会话信息'=> 'SESSION_ID='.session_id(),
);
// 读取项目定义的Trace文件
$traceFile = CONF_PATH.'trace.php';
if(is_file($traceFile)) {
$base = array_merge($base,include $traceFile);
}
$debug = trace();
$tabs = C('TRACE_PAGE_TABS');
foreach ($tabs as $name=>$title){
switch(strtoupper($name)) {
case 'BASE':// 基本信息
$trace[$title] = $base;
break;
case 'FILE': // 文件信息
$trace[$title] = $info;
break;
default:// 调试信息
if(strpos($name,'|')) {// 多组信息
$array = explode('|',$name);
$result = array();
foreach($array as $name){
$result += isset($debug[$name])?$debug[$name]:array();
}
$trace[$title] = $result;
}else{
$trace[$title] = isset($debug[$name])?$debug[$name]:'';
}
}
}
foreach ($trace as $key=>$val){
if(!is_array($val) && empty($val))
$val=array();
if(is_array($val)){
$fire=array(
array('','')
);
foreach($val as $k=>$v){
$fire[]=array($k,$v);
}
fb(array($key,$fire),FirePHP::TABLE);
}else{
fb($val,$key);
}
}
unset($files,$info,$log,$base);
}
/**
+----------------------------------------------------------
* 获取运行时间
+----------------------------------------------------------
*/
private function showTime() {
// 显示运行时间
G('beginTime',$GLOBALS['_beginTime']);
G('viewEndTime');
// 显示详细运行时间
return G('beginTime','viewEndTime').'s ( Load:'.G('beginTime','loadTime').'s Init:'.G('loadTime','initTime').'s Exec:'.G('initTime','viewStartTime').'s Template:'.G('viewStartTime','viewEndTime').'s )';
}
}
function fb()
{
$instance = FirePHP::getInstance(true);
$args = func_get_args();
return call_user_func_array(array($instance,'fb'),$args);
}
class FB
{
/**
* Enable and disable logging to Firebug
*
* @see FirePHP->setEnabled()
* @param boolean $Enabled TRUE to enable, FALSE to disable
* @return void
*/
public static function setEnabled($Enabled)
{
$instance = FirePHP::getInstance(true);
$instance->setEnabled($Enabled);
}
/**
* Check if logging is enabled
*
* @see FirePHP->getEnabled()
* @return boolean TRUE if enabled
*/
public static function getEnabled()
{
$instance = FirePHP::getInstance(true);
return $instance->getEnabled();
}
/**
* Specify a filter to be used when encoding an object
*
* Filters are used to exclude object members.
*
* @see FirePHP->setObjectFilter()
* @param string $Class The class name of the object
* @param array $Filter An array or members to exclude
* @return void
*/
public static function setObjectFilter($Class, $Filter)
{
$instance = FirePHP::getInstance(true);
$instance->setObjectFilter($Class, $Filter);
}
/**
* Set some options for the library
*
* @see FirePHP->setOptions()
* @param array $Options The options to be set
* @return void
*/
public static function setOptions($Options)
{
$instance = FirePHP::getInstance(true);
$instance->setOptions($Options);
}
/**
* Get options for the library
*
* @see FirePHP->getOptions()
* @return array The options
*/
public static function getOptions()
{
$instance = FirePHP::getInstance(true);
return $instance->getOptions();
}
/**
* Log object to firebug
*
* @see http://www.firephp.org/Wiki/Reference/Fb
* @param mixed $Object
* @return true
* @throws Exception
*/
public static function send()
{
$instance = FirePHP::getInstance(true);
$args = func_get_args();
return call_user_func_array(array($instance,'fb'),$args);
}
/**
* Start a group for following messages
*
* Options:
* Collapsed: [true|false]
* Color: [#RRGGBB|ColorName]
*
* @param string $Name
* @param array $Options OPTIONAL Instructions on how to log the group
* @return true
*/
public static function group($Name, $Options=null)
{
$instance = FirePHP::getInstance(true);
return $instance->group($Name, $Options);
}
/**
* Ends a group you have started before
*
* @return true
* @throws Exception
*/
public static function groupEnd()
{
return self::send(null, null, FirePHP::GROUP_END);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::LOG
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public static function log($Object, $Label=null)
{
return self::send($Object, $Label, FirePHP::LOG);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::INFO
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public static function info($Object, $Label=null)
{
return self::send($Object, $Label, FirePHP::INFO);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::WARN
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public static function warn($Object, $Label=null)
{
return self::send($Object, $Label, FirePHP::WARN);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::ERROR
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public static function error($Object, $Label=null)
{
return self::send($Object, $Label, FirePHP::ERROR);
}
/**
* Dumps key and variable to firebug server panel
*
* @see FirePHP::DUMP
* @param string $Key
* @param mixed $Variable
* @return true
* @throws Exception
*/
public static function dump($Key, $Variable)
{
return self::send($Variable, $Key, FirePHP::DUMP);
}
/**
* Log a trace in the firebug console
*
* @see FirePHP::TRACE
* @param string $Label
* @return true
* @throws Exception
*/
public static function trace($Label)
{
return self::send($Label, FirePHP::TRACE);
}
/**
* Log a table in the firebug console
*
* @see FirePHP::TABLE
* @param string $Label
* @param string $Table
* @return true
* @throws Exception
*/
public static function table($Label, $Table)
{
return self::send($Table, $Label, FirePHP::TABLE);
}
}
if (!defined('E_STRICT')) {
define('E_STRICT', 2048);
}
if (!defined('E_RECOVERABLE_ERROR')) {
define('E_RECOVERABLE_ERROR', 4096);
}
if (!defined('E_DEPRECATED')) {
define('E_DEPRECATED', 8192);
}
if (!defined('E_USER_DEPRECATED')) {
define('E_USER_DEPRECATED', 16384);
}
/**
* Sends the given data to the FirePHP Firefox Extension.
* The data can be displayed in the Firebug Console or in the
* "Server" request tab.
*
* For more information see: http://www.firephp.org/
*
* @copyright Copyright (C) 2007-2009 Christoph Dorn
* @author Christoph Dorn <christoph@christophdorn.com>
* @license http://www.opensource.org/licenses/bsd-license.php
* @package FirePHPCore
*/
class FirePHP {
/**
* FirePHP version
*
* @var string
*/
const VERSION = '0.3'; // @pinf replace '0.3' with '%%package.version%%'
/**
* Firebug LOG level
*
* Logs a message to firebug console.
*
* @var string
*/
const LOG = 'LOG';
/**
* Firebug INFO level
*
* Logs a message to firebug console and displays an info icon before the message.
*
* @var string
*/
const INFO = 'INFO';
/**
* Firebug WARN level
*
* Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise.
*
* @var string
*/
const WARN = 'WARN';
/**
* Firebug ERROR level
*
* Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
*
* @var string
*/
const ERROR = 'ERROR';
/**
* Dumps a variable to firebug's server panel
*
* @var string
*/
const DUMP = 'DUMP';
/**
* Displays a stack trace in firebug console
*
* @var string
*/
const TRACE = 'TRACE';
/**
* Displays an exception in firebug console
*
* Increments the firebug error count.
*
* @var string
*/
const EXCEPTION = 'EXCEPTION';
/**
* Displays an table in firebug console
*
* @var string
*/
const TABLE = 'TABLE';
/**
* Starts a group in firebug console
*
* @var string
*/
const GROUP_START = 'GROUP_START';
/**
* Ends a group in firebug console
*
* @var string
*/
const GROUP_END = 'GROUP_END';
/**
* Singleton instance of FirePHP
*
* @var FirePHP
*/
protected static $instance = null;
/**
* Flag whether we are logging from within the exception handler
*
* @var boolean
*/
protected $inExceptionHandler = false;
/**
* Flag whether to throw PHP errors that have been converted to ErrorExceptions
*
* @var boolean
*/
protected $throwErrorExceptions = true;
/**
* Flag whether to convert PHP assertion errors to Exceptions
*
* @var boolean
*/
protected $convertAssertionErrorsToExceptions = true;
/**
* Flag whether to throw PHP assertion errors that have been converted to Exceptions
*
* @var boolean
*/
protected $throwAssertionExceptions = false;
/**
* Wildfire protocol message index
*
* @var int
*/
protected $messageIndex = 1;
/**
* Options for the library
*
* @var array
*/
protected $options = array('maxDepth' => 10,
'maxObjectDepth' => 5,
'maxArrayDepth' => 5,
'useNativeJsonEncode' => true,
'includeLineNumbers' => true);
/**
* Filters used to exclude object members when encoding
*
* @var array
*/
protected $objectFilters = array(
'firephp' => array('objectStack', 'instance', 'json_objectStack'),
'firephp_test_class' => array('objectStack', 'instance', 'json_objectStack')
);
/**
* A stack of objects used to detect recursion during object encoding
*
* @var object
*/
protected $objectStack = array();
/**
* Flag to enable/disable logging
*
* @var boolean
*/
protected $enabled = true;
/**
* The insight console to log to if applicable
*
* @var object
*/
protected $logToInsightConsole = null;
/**
* When the object gets serialized only include specific object members.
*
* @return array
*/
public function __sleep()
{
return array('options','objectFilters','enabled');
}
/**
* Gets singleton instance of FirePHP
*
* @param boolean $AutoCreate
* @return FirePHP
*/
public static function getInstance($AutoCreate = false)
{
if ($AutoCreate===true && !self::$instance) {
self::init();
}
return self::$instance;
}
/**
* Creates FirePHP object and stores it for singleton access
*
* @return FirePHP
*/
public static function init()
{
return self::setInstance(new self());
}
/**
* Set the instance of the FirePHP singleton
*
* @param FirePHP $instance The FirePHP object instance
* @return FirePHP
*/
public static function setInstance($instance)
{
return self::$instance = $instance;
}
/**
* Set an Insight console to direct all logging calls to
*
* @param object $console The console object to log to
* @return void
*/
public function setLogToInsightConsole($console)
{
if(is_string($console)) {
if(get_class($this)!='FirePHP_Insight' && !is_subclass_of($this, 'FirePHP_Insight')) {
throw new Exception('FirePHP instance not an instance or subclass of FirePHP_Insight!');
}
$this->logToInsightConsole = $this->to('request')->console($console);
} else {
$this->logToInsightConsole = $console;
}
}
/**
* Enable and disable logging to Firebug
*
* @param boolean $Enabled TRUE to enable, FALSE to disable
* @return void
*/
public function setEnabled($Enabled)
{
$this->enabled = $Enabled;
}
/**
* Check if logging is enabled
*
* @return boolean TRUE if enabled
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Specify a filter to be used when encoding an object
*
* Filters are used to exclude object members.
*
* @param string $Class The class name of the object
* @param array $Filter An array of members to exclude
* @return void
*/
public function setObjectFilter($Class, $Filter)
{
$this->objectFilters[strtolower($Class)] = $Filter;
}
/**
* Set some options for the library
*
* Options:
* - maxDepth: The maximum depth to traverse (default: 10)
* - maxObjectDepth: The maximum depth to traverse objects (default: 5)
* - maxArrayDepth: The maximum depth to traverse arrays (default: 5)
* - useNativeJsonEncode: If true will use json_encode() (default: true)
* - includeLineNumbers: If true will include line numbers and filenames (default: true)
*
* @param array $Options The options to be set
* @return void
*/
public function setOptions($Options)
{
$this->options = array_merge($this->options,$Options);
}
/**
* Get options from the library
*
* @return array The currently set options
*/
public function getOptions()
{
return $this->options;
}
/**
* Set an option for the library
*
* @param string $Name
* @param mixed $Value
* @throws Exception
* @return void
*/
public function setOption($Name, $Value)
{
if (!isset($this->options[$Name])) {
throw $this->newException('Unknown option: ' . $Name);
}
$this->options[$Name] = $Value;
}
/**
* Get an option from the library
*
* @param string $Name
* @throws Exception
* @return mixed
*/
public function getOption($Name)
{
if (!isset($this->options[$Name])) {
throw $this->newException('Unknown option: ' . $Name);
}
return $this->options[$Name];
}
/**
* Register FirePHP as your error handler
*
* Will throw exceptions for each php error.
*
* @return mixed Returns a string containing the previously defined error handler (if any)
*/
public function registerErrorHandler($throwErrorExceptions = false)
{
//NOTE: The following errors will not be caught by this error handler:
// E_ERROR, E_PARSE, E_CORE_ERROR,
// E_CORE_WARNING, E_COMPILE_ERROR,
// E_COMPILE_WARNING, E_STRICT
$this->throwErrorExceptions = $throwErrorExceptions;
return set_error_handler(array($this,'errorHandler'));
}
/**
* FirePHP's error handler
*
* Throws exception for each php error that will occur.
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param array $errcontext
*/
public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
{
// Don't throw exception if error reporting is switched off
if (error_reporting() == 0) {
return;
}
// Only throw exceptions for errors we are asking for
if (error_reporting() & $errno) {
$exception = new ErrorException($errstr, 0, $errno, $errfile, $errline);
if ($this->throwErrorExceptions) {
throw $exception;
} else {
$this->fb($exception);
}
}
}
/**
* Register FirePHP as your exception handler
*
* @return mixed Returns the name of the previously defined exception handler,
* or NULL on error.
* If no previous handler was defined, NULL is also returned.
*/
public function registerExceptionHandler()
{
return set_exception_handler(array($this,'exceptionHandler'));
}
/**
* FirePHP's exception handler
*
* Logs all exceptions to your firebug console and then stops the script.
*
* @param Exception $Exception
* @throws Exception
*/
function exceptionHandler($Exception)
{
$this->inExceptionHandler = true;
header('HTTP/1.1 500 Internal Server Error');
try {
$this->fb($Exception);
} catch (Exception $e) {
echo 'We had an exception: ' . $e;
}
$this->inExceptionHandler = false;
}
/**
* Register FirePHP driver as your assert callback
*
* @param boolean $convertAssertionErrorsToExceptions
* @param boolean $throwAssertionExceptions
* @return mixed Returns the original setting or FALSE on errors
*/
public function registerAssertionHandler($convertAssertionErrorsToExceptions = true, $throwAssertionExceptions = false)
{
$this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions;
$this->throwAssertionExceptions = $throwAssertionExceptions;
if ($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) {
throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!');
}
return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler'));
}
/**
* FirePHP's assertion handler
*
* Logs all assertions to your firebug console and then stops the script.
*
* @param string $file File source of assertion
* @param int $line Line source of assertion
* @param mixed $code Assertion code
*/
public function assertionHandler($file, $line, $code)
{
if ($this->convertAssertionErrorsToExceptions) {
$exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line);
if ($this->throwAssertionExceptions) {
throw $exception;
} else {
$this->fb($exception);
}
} else {
$this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line));
}
}
/**
* Start a group for following messages.
*
* Options:
* Collapsed: [true|false]
* Color: [#RRGGBB|ColorName]
*
* @param string $Name
* @param array $Options OPTIONAL Instructions on how to log the group
* @return true
* @throws Exception
*/
public function group($Name, $Options = null)
{
if (!$Name) {
throw $this->newException('You must specify a label for the group!');
}
if ($Options) {
if (!is_array($Options)) {
throw $this->newException('Options must be defined as an array!');
}
if (array_key_exists('Collapsed', $Options)) {
$Options['Collapsed'] = ($Options['Collapsed'])?'true':'false';
}
}
return $this->fb(null, $Name, FirePHP::GROUP_START, $Options);
}
/**
* Ends a group you have started before
*
* @return true
* @throws Exception
*/
public function groupEnd()
{
return $this->fb(null, null, FirePHP::GROUP_END);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::LOG
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function log($Object, $Label = null, $Options = array())
{
return $this->fb($Object, $Label, FirePHP::LOG, $Options);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::INFO
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function info($Object, $Label = null, $Options = array())
{
return $this->fb($Object, $Label, FirePHP::INFO, $Options);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::WARN
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function warn($Object, $Label = null, $Options = array())
{
return $this->fb($Object, $Label, FirePHP::WARN, $Options);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::ERROR
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function error($Object, $Label = null, $Options = array())
{
return $this->fb($Object, $Label, FirePHP::ERROR, $Options);
}
/**
* Dumps key and variable to firebug server panel
*
* @see FirePHP::DUMP
* @param string $Key
* @param mixed $Variable
* @return true
* @throws Exception
*/
public function dump($Key, $Variable, $Options = array())
{
if (!is_string($Key)) {
throw $this->newException('Key passed to dump() is not a string');
}
if (strlen($Key)>100) {
throw $this->newException('Key passed to dump() is longer than 100 characters');
}
if (!preg_match_all('/^[a-zA-Z0-9-_\.:]*$/', $Key, $m)) {
throw $this->newException('Key passed to dump() contains invalid characters [a-zA-Z0-9-_\.:]');
}
return $this->fb($Variable, $Key, FirePHP::DUMP, $Options);
}
/**
* Log a trace in the firebug console
*
* @see FirePHP::TRACE
* @param string $Label
* @return true
* @throws Exception
*/
public function trace($Label)
{
return $this->fb($Label, FirePHP::TRACE);
}
/**
* Log a table in the firebug console
*
* @see FirePHP::TABLE
* @param string $Label
* @param string $Table
* @return true
* @throws Exception
*/
public function table($Label, $Table, $Options = array())
{
return $this->fb($Table, $Label, FirePHP::TABLE, $Options);
}
/**
* Insight API wrapper
*
* @see Insight_Helper::to()
*/
public static function to()
{
$instance = self::getInstance();
if (!method_exists($instance, "_to")) {
throw new Exception("FirePHP::to() implementation not loaded");
}
$args = func_get_args();
return call_user_func_array(array($instance, '_to'), $args);
}
/**
* Insight API wrapper
*
* @see Insight_Helper::plugin()
*/
public static function plugin()
{
$instance = self::getInstance();
if (!method_exists($instance, "_plugin")) {
throw new Exception("FirePHP::plugin() implementation not loaded");
}
$args = func_get_args();
return call_user_func_array(array($instance, '_plugin'), $args);
}
/**
* Check if FirePHP is installed on client
*
* @return boolean
*/
public function detectClientExtension()
{
// Check if FirePHP is installed on client via User-Agent header
if (@preg_match_all('/\sFirePHP\/([\.\d]*)\s?/si',$this->getUserAgent(),$m) &&
version_compare($m[1][0],'0.0.6','>=')) {
return true;
} else
// Check if FirePHP is installed on client via X-FirePHP-Version header
if (@preg_match_all('/^([\.\d]*)$/si',$this->getRequestHeader("X-FirePHP-Version"),$m) &&
version_compare($m[1][0],'0.0.6','>=')) {
return true;
}
return false;
}
/**
* Log varible to Firebug
*
* @see http://www.firephp.org/Wiki/Reference/Fb
* @param mixed $Object The variable to be logged
* @return true Return TRUE if message was added to headers, FALSE otherwise
* @throws Exception
*/
public function fb($Object)
{
if($this instanceof FirePHP_Insight && method_exists($this, '_logUpgradeClientMessage')) {
if(!FirePHP_Insight::$upgradeClientMessageLogged) { // avoid infinite recursion as _logUpgradeClientMessage() logs a message
$this->_logUpgradeClientMessage();
}
}
static $insightGroupStack = array();
if (!$this->getEnabled()) {
return false;
}
if ($this->headersSent($filename, $linenum)) {
// If we are logging from within the exception handler we cannot throw another exception
if ($this->inExceptionHandler) {
// Simply echo the error out to the page
echo '<div style="border: 2px solid red; font-family: Arial; font-size: 12px; background-color: lightgray; padding: 5px;"><span style="color: red; font-weight: bold;">FirePHP ERROR:</span> Headers already sent in <b>'.$filename.'</b> on line <b>'.$linenum.'</b>. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.</div>';
} else {
throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.');
}
}
$Type = null;
$Label = null;
$Options = array();
if (func_num_args()==1) {
} else
if (func_num_args()==2) {
switch(func_get_arg(1)) {
case self::LOG:
case self::INFO:
case self::WARN:
case self::ERROR:
case self::DUMP:
case self::TRACE:
case self::EXCEPTION:
case self::TABLE:
case self::GROUP_START:
case self::GROUP_END:
$Type = func_get_arg(1);
break;
default:
$Label = func_get_arg(1);
break;
}
} else
if (func_num_args()==3) {
$Type = func_get_arg(2);
$Label = func_get_arg(1);
} else
if (func_num_args()==4) {
$Type = func_get_arg(2);
$Label = func_get_arg(1);
$Options = func_get_arg(3);
} else {
throw $this->newException('Wrong number of arguments to fb() function!');
}
if($this->logToInsightConsole!==null && (get_class($this)=='FirePHP_Insight' || is_subclass_of($this, 'FirePHP_Insight'))) {
$msg = $this->logToInsightConsole;
if ($Object instanceof Exception) {
$Type = self::EXCEPTION;
}
if($Label && $Type!=self::TABLE && $Type!=self::GROUP_START) {
$msg = $msg->label($Label);
}
switch($Type) {
case self::DUMP:
case self::LOG:
return $msg->log($Object);
case self::INFO:
return $msg->info($Object);
case self::WARN:
return $msg->warn($Object);
case self::ERROR:
return $msg->error($Object);
case self::TRACE:
return $msg->trace($Object);
case self::EXCEPTION:
return $this->plugin('engine')->handleException($Object, $msg);
case self::TABLE:
if (isset($Object[0]) && !is_string($Object[0]) && $Label) {
$Object = array($Label, $Object);
}
return $msg->table($Object[0], array_slice($Object[1],1), $Object[1][0]);
case self::GROUP_START:
$insightGroupStack[] = $msg->group(md5($Label))->open();
return $msg->log($Label);
case self::GROUP_END:
if(count($insightGroupStack)==0) {
throw new Error('Too many groupEnd() as opposed to group() calls!');
}
$group = array_pop($insightGroupStack);
return $group->close();
default:
return $msg->log($Object);
}
}
if (!$this->detectClientExtension()) {
return false;
}
$meta = array();
$skipFinalObjectEncode = false;
if ($Object instanceof Exception) {
$meta['file'] = $this->_escapeTraceFile($Object->getFile());
$meta['line'] = $Object->getLine();
$trace = $Object->getTrace();
if ($Object instanceof ErrorException
&& isset($trace[0]['function'])
&& $trace[0]['function']=='errorHandler'
&& isset($trace[0]['class'])
&& $trace[0]['class']=='FirePHP') {
$severity = false;
switch($Object->getSeverity()) {
case E_WARNING: $severity = 'E_WARNING'; break;
case E_NOTICE: $severity = 'E_NOTICE'; break;
case E_USER_ERROR: $severity = 'E_USER_ERROR'; break;
case E_USER_WARNING: $severity = 'E_USER_WARNING'; break;
case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break;
case E_STRICT: $severity = 'E_STRICT'; break;
case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break;
case E_DEPRECATED: $severity = 'E_DEPRECATED'; break;
case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break;
}
$Object = array('Class'=>get_class($Object),
'Message'=>$severity.': '.$Object->getMessage(),
'File'=>$this->_escapeTraceFile($Object->getFile()),
'Line'=>$Object->getLine(),
'Type'=>'trigger',
'Trace'=>$this->_escapeTrace(array_splice($trace,2)));
$skipFinalObjectEncode = true;
} else {
$Object = array('Class'=>get_class($Object),
'Message'=>$Object->getMessage(),
'File'=>$this->_escapeTraceFile($Object->getFile()),
'Line'=>$Object->getLine(),
'Type'=>'throw',
'Trace'=>$this->_escapeTrace($trace));
$skipFinalObjectEncode = true;
}
$Type = self::EXCEPTION;
} else
if ($Type==self::TRACE) {
$trace = debug_backtrace();
if (!$trace) return false;
for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
if (isset($trace[$i]['class'])
&& isset($trace[$i]['file'])
&& ($trace[$i]['class']=='FirePHP'
|| $trace[$i]['class']=='FB')
&& (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
|| substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
/* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
} else
if (isset($trace[$i]['class'])
&& isset($trace[$i+1]['file'])
&& $trace[$i]['class']=='FirePHP'
&& substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
/* Skip fb() */
} else
if ($trace[$i]['function']=='fb'
|| $trace[$i]['function']=='trace'
|| $trace[$i]['function']=='send') {
$Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
'Message'=>$trace[$i]['args'][0],
'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
$skipFinalObjectEncode = true;
$meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
$meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
break;
}
}
} else
if ($Type==self::TABLE) {
if (isset($Object[0]) && is_string($Object[0])) {
$Object[1] = $this->encodeTable($Object[1]);
} else {
$Object = $this->encodeTable($Object);
}
$skipFinalObjectEncode = true;
} else
if ($Type==self::GROUP_START) {
if (!$Label) {
throw $this->newException('You must specify a label for the group!');
}
} else {
if ($Type===null) {
$Type = self::LOG;
}
}
if ($this->options['includeLineNumbers']) {
if (!isset($meta['file']) || !isset($meta['line'])) {
$trace = debug_backtrace();
for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
if (isset($trace[$i]['class'])
&& isset($trace[$i]['file'])
&& ($trace[$i]['class']=='FirePHP'
|| $trace[$i]['class']=='FB')
&& (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
|| substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
/* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
} else
if (isset($trace[$i]['class'])
&& isset($trace[$i+1]['file'])
&& $trace[$i]['class']=='FirePHP'
&& substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
/* Skip fb() */
} else
if (isset($trace[$i]['file'])
&& substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
/* Skip FB::fb() */
} else {
$meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
$meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
break;
}
}
}
} else {
unset($meta['file']);
unset($meta['line']);
}
$this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
$this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION);
$structure_index = 1;
if ($Type==self::DUMP) {
$structure_index = 2;
$this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
} else {
$this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
}
if ($Type==self::DUMP) {
$msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
} else {
$msg_meta = $Options;
$msg_meta['Type'] = $Type;
if ($Label!==null) {
$msg_meta['Label'] = $Label;
}
if (isset($meta['file']) && !isset($msg_meta['File'])) {
$msg_meta['File'] = $meta['file'];
}
if (isset($meta['line']) && !isset($msg_meta['Line'])) {
$msg_meta['Line'] = $meta['line'];
}
$msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
}
$parts = explode("\n",chunk_split($msg, 5000, "\n"));
for( $i=0 ; $i<count($parts) ; $i++) {
$part = $parts[$i];
if ($part) {
if (count($parts)>2) {
// Message needs to be split into multiple parts
$this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
(($i==0)?strlen($msg):'')
. '|' . $part . '|'
. (($i<count($parts)-2)?'\\':''));
} else {
$this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
strlen($part) . '|' . $part . '|');
}
$this->messageIndex++;
if ($this->messageIndex > 99999) {
throw $this->newException('Maximum number (99,999) of messages reached!');
}
}
}
$this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
return true;
}
/**
* Standardizes path for windows systems.
*
* @param string $Path
* @return string
*/
protected function _standardizePath($Path)
{
return preg_replace('/\\\\+/','/',$Path);
}
/**
* Escape trace path for windows systems
*
* @param array $Trace
* @return array
*/
protected function _escapeTrace($Trace)
{
if (!$Trace) return $Trace;
for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
if (isset($Trace[$i]['file'])) {
$Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
}
if (isset($Trace[$i]['args'])) {
$Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
}
}
return $Trace;
}
/**
* Escape file information of trace for windows systems
*
* @param string $File
* @return string
*/
protected function _escapeTraceFile($File)
{
/* Check if we have a windows filepath */
if (strpos($File,'\\')) {
/* First strip down to single \ */
$file = preg_replace('/\\\\+/','\\',$File);
return $file;
}
return $File;
}
/**
* Check if headers have already been sent
*
* @param string $Filename
* @param integer $Linenum
*/
protected function headersSent(&$Filename, &$Linenum)
{
return headers_sent($Filename, $Linenum);
}
/**
* Send header
*
* @param string $Name
* @param string $Value
*/
protected function setHeader($Name, $Value)
{
return header($Name.': '.$Value);
}
/**
* Get user agent
*
* @return string|false
*/
protected function getUserAgent()
{
if (!isset($_SERVER['HTTP_USER_AGENT'])) return false;
return $_SERVER['HTTP_USER_AGENT'];
}
/**
* Get all request headers
*
* @return array
*/
public static function getAllRequestHeaders() {
static $_cached_headers = false;
if($_cached_headers!==false) {
return $_cached_headers;
}
$headers = array();
if(function_exists('getallheaders')) {
foreach( getallheaders() as $name => $value ) {
$headers[strtolower($name)] = $value;
}
} else {
foreach($_SERVER as $name => $value) {
if(substr($name, 0, 5) == 'HTTP_') {
$headers[strtolower(str_replace(' ', '-', str_replace('_', ' ', substr($name, 5))))] = $value;
}
}
}
return $_cached_headers = $headers;
}
/**
* Get a request header
*
* @return string|false
*/
protected function getRequestHeader($Name)
{
$headers = self::getAllRequestHeaders();
if (isset($headers[strtolower($Name)])) {
return $headers[strtolower($Name)];
}
return false;
}
/**
* Returns a new exception
*
* @param string $Message
* @return Exception
*/
protected function newException($Message)
{
return new Exception($Message);
}
/**
* Encode an object into a JSON string
*
* Uses PHP's jeson_encode() if available
*
* @param object $Object The object to be encoded
* @return string The JSON string
*/
public function jsonEncode($Object, $skipObjectEncode = false)
{
if (!$skipObjectEncode) {
$Object = $this->encodeObject($Object);
}
if (function_exists('json_encode')
&& $this->options['useNativeJsonEncode']!=false) {
return json_encode($Object);
} else {
return $this->json_encode($Object);
}
}
/**
* Encodes a table by encoding each row and column with encodeObject()
*
* @param array $Table The table to be encoded
* @return array
*/
protected function encodeTable($Table)
{
if (!$Table) return $Table;
$new_table = array();
foreach($Table as $row) {
if (is_array($row)) {
$new_row = array();
foreach($row as $item) {
$new_row[] = $this->encodeObject($item);
}
$new_table[] = $new_row;
}
}
return $new_table;
}
/**
* Encodes an object including members with
* protected and private visibility
*
* @param Object $Object The object to be encoded
* @param int $Depth The current traversal depth
* @return array All members of the object
*/
protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $MaxDepth = 1)
{
if ($MaxDepth > $this->options['maxDepth']) {
return '** Max Depth ('.$this->options['maxDepth'].') **';
}
$return = array();
if (is_resource($Object)) {
return '** '.(string)$Object.' **';
} else
if (is_object($Object)) {
if ($ObjectDepth > $this->options['maxObjectDepth']) {
return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **';
}
foreach ($this->objectStack as $refVal) {
if ($refVal === $Object) {
return '** Recursion ('.get_class($Object).') **';
}
}
array_push($this->objectStack, $Object);
$return['__className'] = $class = get_class($Object);
$class_lower = strtolower($class);
$reflectionClass = new ReflectionClass($class);
$properties = array();
foreach( $reflectionClass->getProperties() as $property) {
$properties[$property->getName()] = $property;
}
$members = (array)$Object;
foreach( $properties as $plain_name => $property ) {
$name = $raw_name = $plain_name;
if ($property->isStatic()) {
$name = 'static:'.$name;
}
if ($property->isPublic()) {
$name = 'public:'.$name;
} else
if ($property->isPrivate()) {
$name = 'private:'.$name;
$raw_name = "\0".$class."\0".$raw_name;
} else
if ($property->isProtected()) {
$name = 'protected:'.$name;
$raw_name = "\0".'*'."\0".$raw_name;
}
if (!(isset($this->objectFilters[$class_lower])
&& is_array($this->objectFilters[$class_lower])
&& in_array($plain_name,$this->objectFilters[$class_lower]))) {
if (array_key_exists($raw_name,$members)
&& !$property->isStatic()) {
$return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1, $MaxDepth + 1);
} else {
if (method_exists($property,'setAccessible')) {
$property->setAccessible(true);
$return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1);
} else
if ($property->isPublic()) {
$return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1);
} else {
$return[$name] = '** Need PHP 5.3 to get value **';
}
}
} else {
$return[$name] = '** Excluded by Filter **';
}
}
// Include all members that are not defined in the class
// but exist in the object
foreach( $members as $raw_name => $value ) {
$name = $raw_name;
if ($name{0} == "\0") {
$parts = explode("\0", $name);
$name = $parts[2];
}
$plain_name = $name;
if (!isset($properties[$name])) {
$name = 'undeclared:'.$name;
if (!(isset($this->objectFilters[$class_lower])
&& is_array($this->objectFilters[$class_lower])
&& in_array($plain_name,$this->objectFilters[$class_lower]))) {
$return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1, $MaxDepth + 1);
} else {
$return[$name] = '** Excluded by Filter **';
}
}
}
array_pop($this->objectStack);
} elseif (is_array($Object)) {
if ($ArrayDepth > $this->options['maxArrayDepth']) {
return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **';
}
foreach ($Object as $key => $val) {
// Encoding the $GLOBALS PHP array causes an infinite loop
// if the recursion is not reset here as it contains
// a reference to itself. This is the only way I have come up
// with to stop infinite recursion in this case.
if ($key=='GLOBALS'
&& is_array($val)
&& array_key_exists('GLOBALS',$val)) {
$val['GLOBALS'] = '** Recursion (GLOBALS) **';
}
$return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1, $MaxDepth + 1);
}
} else {
if (self::is_utf8($Object)) {
return $Object;
} else {
return utf8_encode($Object);
}
}
return $return;
}
/**
* Returns true if $string is valid UTF-8 and false otherwise.
*
* @param mixed $str String to be tested
* @return boolean
*/
protected static function is_utf8($str)
{
if(function_exists('mb_detect_encoding')) {
return (mb_detect_encoding($str) == 'UTF-8');
}
$c=0; $b=0;
$bits=0;
$len=strlen($str);
for($i=0; $i<$len; $i++){
$c=ord($str[$i]);
if ($c > 128){
if (($c >= 254)) return false;
elseif ($c >= 252) $bits=6;
elseif ($c >= 248) $bits=5;
elseif ($c >= 240) $bits=4;
elseif ($c >= 224) $bits=3;
elseif ($c >= 192) $bits=2;
else return false;
if (($i+$bits) > $len) return false;
while($bits > 1){
$i++;
$b=ord($str[$i]);
if ($b < 128 || $b > 191) return false;
$bits--;
}
}
}
return true;
}
/**
* Converts to and from JSON format.
*
* JSON (JavaScript Object Notation) is a lightweight data-interchange
* format. It is easy for humans to read and write. It is easy for machines
* to parse and generate. It is based on a subset of the JavaScript
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
* This feature can also be found in Python. JSON is a text format that is
* completely language independent but uses conventions that are familiar
* to programmers of the C-family of languages, including C, C++, C#, Java,
* JavaScript, Perl, TCL, and many others. These properties make JSON an
* ideal data-interchange language.
*
* This package provides a simple encoder and decoder for JSON notation. It
* is intended for use with client-side Javascript applications that make
* use of HTTPRequest to perform server communication functions - data can
* be encoded into JSON notation for use in a client-side javascript, or
* decoded from incoming Javascript requests. JSON format is native to
* Javascript, and can be directly eval()'ed with no further parsing
* overhead
*
* All strings should be in ASCII or UTF-8 format!
*
* LICENSE: Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met: Redistributions of source code must retain the
* above copyright notice, this list of conditions and the following
* disclaimer. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* @category
* @package Services_JSON
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
* @author Christoph Dorn <christoph@christophdorn.com>
* @copyright 2005 Michal Migurski
* @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
* @license http://www.opensource.org/licenses/bsd-license.php
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
*/
/**
* Keep a list of objects as we descend into the array so we can detect recursion.
*/
private $json_objectStack = array();
/**
* convert a string from one UTF-8 char to one UTF-16 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf8 UTF-8 character
* @return string UTF-16 character
* @access private
*/
private function json_utf82utf16($utf8)
{
// oh please oh please oh please oh please oh please
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
}
switch(strlen($utf8)) {
case 1:
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return $utf8;
case 2:
// return a UTF-16 character from a 2-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x07 & (ord($utf8{0}) >> 2))
. chr((0xC0 & (ord($utf8{0}) << 6))
| (0x3F & ord($utf8{1})));
case 3:
// return a UTF-16 character from a 3-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr((0xF0 & (ord($utf8{0}) << 4))
| (0x0F & (ord($utf8{1}) >> 2)))
. chr((0xC0 & (ord($utf8{1}) << 6))
| (0x7F & ord($utf8{2})));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* encodes an arbitrary variable into JSON format
*
* @param mixed $var any number, boolean, string, array, or object to be encoded.
* see argument 1 to Services_JSON() above for array-parsing behavior.
* if var is a strng, note that encode() always expects it
* to be in ASCII or UTF-8 format!
*
* @return mixed JSON string representation of input var or an error if a problem occurs
* @access public
*/
private function json_encode($var)
{
if (is_object($var)) {
if (in_array($var,$this->json_objectStack)) {
return '"** Recursion **"';
}
}
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
case 'NULL':
return 'null';
case 'integer':
return (int) $var;
case 'double':
case 'float':
return (float) $var;
case 'string':
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
$ascii = '';
$strlen_var = strlen($var);
/*
* Iterate over every character in the string,
* escaping with a slash or encoding to UTF-8 where necessary
*/
for ($c = 0; $c < $strlen_var; ++$c) {
$ord_var_c = ord($var{$c});
switch (true) {
case $ord_var_c == 0x08:
$ascii .= '\b';
break;
case $ord_var_c == 0x09:
$ascii .= '\t';
break;
case $ord_var_c == 0x0A:
$ascii .= '\n';
break;
case $ord_var_c == 0x0C:
$ascii .= '\f';
break;
case $ord_var_c == 0x0D:
$ascii .= '\r';
break;
case $ord_var_c == 0x22:
case $ord_var_c == 0x2F:
case $ord_var_c == 0x5C:
// double quote, slash, slosh
$ascii .= '\\'.$var{$c};
break;
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
// characters U-00000000 - U-0000007F (same as ASCII)
$ascii .= $var{$c};
break;
case (($ord_var_c & 0xE0) == 0xC0):
// characters U-00000080 - U-000007FF, mask 110XXXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
$c += 1;
$utf16 = $this->json_utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF0) == 0xE0):
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}));
$c += 2;
$utf16 = $this->json_utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF8) == 0xF0):
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}));
$c += 3;
$utf16 = $this->json_utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFC) == 0xF8):
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}));
$c += 4;
$utf16 = $this->json_utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFE) == 0xFC):
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}),
ord($var{$c + 5}));
$c += 5;
$utf16 = $this->json_utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
}
return '"'.$ascii.'"';
case 'array':
/*
* As per JSON spec if any array key is not an integer
* we must treat the the whole array as an object. We
* also try to catch a sparsely populated associative
* array with numeric keys here because some JS engines
* will create an array with empty indexes up to
* max_index which can cause memory issues and because
* the keys, which may be relevant, will be remapped
* otherwise.
*
* As per the ECMA and JSON specification an object may
* have any string as a property. Unfortunately due to
* a hole in the ECMA specification if the key is a
* ECMA reserved word or starts with a digit the
* parameter is only accessible using ECMAScript's
* bracket notation.
*/
// treat as a JSON object
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
$this->json_objectStack[] = $var;
$properties = array_map(array($this, 'json_name_value'),
array_keys($var),
array_values($var));
array_pop($this->json_objectStack);
foreach($properties as $property) {
if ($property instanceof Exception) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
}
$this->json_objectStack[] = $var;
// treat it like a regular array
$elements = array_map(array($this, 'json_encode'), $var);
array_pop($this->json_objectStack);
foreach($elements as $element) {
if ($element instanceof Exception) {
return $element;
}
}
return '[' . join(',', $elements) . ']';
case 'object':
$vars = self::encodeObject($var);
$this->json_objectStack[] = $var;
$properties = array_map(array($this, 'json_name_value'),
array_keys($vars),
array_values($vars));
array_pop($this->json_objectStack);
foreach($properties as $property) {
if ($property instanceof Exception) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
default:
return null;
}
}
/**
* array-walking function for use in generating JSON-formatted name-value pairs
*
* @param string $name name of key to use
* @param mixed $value reference to an array element to be encoded
*
* @return string JSON-formatted name-value pair, like '"name":value'
* @access private
*/
private function json_name_value($name, $value)
{
// Encoding the $GLOBALS PHP array causes an infinite loop
// if the recursion is not reset here as it contains
// a reference to itself. This is the only way I have come up
// with to stop infinite recursion in this case.
if ($name=='GLOBALS'
&& is_array($value)
&& array_key_exists('GLOBALS',$value)) {
$value['GLOBALS'] = '** Recursion **';
}
$encoded_value = $this->json_encode($value);
if ($encoded_value instanceof Exception) {
return $encoded_value;
}
return $this->json_encode(strval($name)) . ':' . $encoded_value;
}
/**
* @deprecated
*/
public function setProcessorUrl($URL)
{
trigger_error("The FirePHP::setProcessorUrl() method is no longer supported", E_USER_DEPRECATED);
}
/**
* @deprecated
*/
public function setRendererUrl($URL)
{
trigger_error("The FirePHP::setRendererUrl() method is no longer supported", E_USER_DEPRECATED);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 机器人检测
* @category Extend
* @package Extend
* @subpackage Behavior
* @author liu21st <liu21st@gmail.com>
*/
class RobotCheckBehavior extends Behavior {
protected $options = array(
'LIMIT_ROBOT_VISIT' => true, // 禁止机器人访问
);
public function run(&$params) {
// 机器人访问检测
if(C('LIMIT_ROBOT_VISIT') && self::isRobot()) {
// 禁止机器人访问
exit('Access Denied');
}
}
static private function isRobot() {
static $_robot = null;
if(is_null($_robot)) {
$spiders = 'Bot|Crawl|Spider|slurp|sohu-search|lycos|robozilla';
$browsers = 'MSIE|Netscape|Opera|Konqueror|Mozilla';
if(preg_match("/($browsers)/", $_SERVER['HTTP_USER_AGENT'])) {
$_robot = false ;
} elseif(preg_match("/($spiders)/", $_SERVER['HTTP_USER_AGENT'])) {
$_robot = true;
} else {
$_robot = false;
}
}
return $_robot;
}
}
<?php
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614<www.3g4k.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 升级短信通知, 如果有ThinkPHP新版升级,或者重要的更新,会发送短信通知你。
* 需要使用SAE的短信服务。请先找一个SAE的应用开通短信服务。
* 使用步骤如下:
* 1,在项目的Conf目录下建立tags.php配置文件,内容如下:
* <code>
* <?php
* return array(
* 'app_init' => array('UpgradeNotice')
* );
* </code>
*
* 2,将此文件放在项目的Lib/Behavior文件夹下。
*注:在SAE上面使用时,以上两步可以省略
* 3,在config.php中配置:
* 'UPGRADE_NOTICE_ON'=>true,//开启短信升级提醒功能
* 'UPGRADE_NOTICE_AKEY'=>'your akey',//SAE应用的AKEY,如果在SAE上使用可以不填
* 'UPGRADE_NOTICE_SKEY'=>'your skey',//SAE应用的SKEY,如果在SAE上使用可以不填
*'UPGRADE_NOTICE_MOBILE'=>'136456789',//接受短信的手机号
*'UPGRADE_NOTICE_CHECK_INTERVAL' => 604800,//检测频率,单位秒,默认是一周
*'UPGRADE_CURRENT_VERSION'=>'0',//升级后的版本号,会在短信中告诉你填写什么
*UPGRADE_NOTICE_DEBUG=>true, //调试默认,如果为true,UPGRADE_NOTICE_CHECK_INTERVAL配置不起作用,每次都会进行版本检查,此时用于调试,调试完毕后请设置次配置为false
*
*/
class UpgradeNoticeBehavior extends Behavior {
// 行为参数定义(默认值) 可在项目配置中覆盖
protected $options = array(
'UPGRADE_NOTICE_ON' => false, // 是否开启升级提醒
'UPGRADE_NOTICE_DEBUG'=>false,
'UPGRADE_NOTICE_QUEUE'=>'',//队列名称, 在SAE平台上设置
'UPGRADE_NOTICE_AKEY' => '', //SAE应用的AKEY
'UPGRADE_NOTICE_SKEY' => '', //SAE应用的SKEY
'UPGRADE_NOTICE_MOBILE' => '', //接受短信的手机号
'UPGRADE_CURRENT_VERSION'=>'0',
'UPGRADE_NOTICE_CHECK_INTERVAL' => 604800, //检测频率,单位秒,默认是一周
);
protected $header_ = '';
protected $httpCode_;
protected $httpDesc_;
protected $accesskey_;
protected $secretkey_;
public function run(&$params) {
if (C('UPGRADE_NOTICE_ON') && (!S('think_upgrade_interval') || C('UPGRADE_NOTICE_DEBUG'))) {
if(IS_SAE && C('UPGRADE_NOTICE_QUEUE') && !isset($_POST['think_upgrade_queque'])){
$queue=new SaeTaskQueue(C('UPGRADE_NOTICE_QUEUE'));
$queue->addTask('http://'.$_SERVER['HTTP_HOST'].__APP__,'think_upgrade_queque=1');
if(!$queue->push()){
trace('升级提醒队列执行失败,错误原因:'.$queue->errmsg(), '升级通知出错', 'NOTIC', true);
}
return ;
}
$akey = C('UPGRADE_NOTICE_AKEY');
$skey = C('UPGRADE_NOTICE_SKEY');
$this->accesskey_ = $akey ? $akey : (defined('SAE_ACCESSKEY') ? SAE_ACCESSKEY : '');
$this->secretkey_ = $skey ? $skey : (defined('SAE_SECRETKEY') ? SAE_SECRETKEY : '');
$current_version = C('UPGRADE_CURRENT_VERSION');
//读取接口
$info = $this->send('http://sinaclouds.sinaapp.com/thinkapi/upgrade.php?v=' . $current_version);
if ($info['version'] != $current_version) {
if($this->send_sms($info['msg'])) trace($info['msg'], '升级通知成功', 'NOTIC', true); //发送升级短信
}
S('think_upgrade_interval', true, C('UPGRADE_NOTICE_CHECK_INTERVAL'));
}
}
private function send_sms($msg) {
$timestamp=time();
$url = 'http://inno.smsinter.sina.com.cn/sae_sms_service/sendsms.php'; //发送短信的接口地址
$content = "FetchUrl" . $url . "TimeStamp" . $timestamp . "AccessKey" . $this->accesskey_;
$signature = (base64_encode(hash_hmac('sha256', $content, $this->secretkey_, true)));
$headers = array(
"FetchUrl: $url",
"AccessKey: ".$this->accesskey_,
"TimeStamp: " . $timestamp,
"Signature: $signature"
);
$data = array(
'mobile' => C('UPGRADE_NOTICE_MOBILE') ,
'msg' => $msg,
'encoding' => 'UTF-8'
);
if(!$ret = $this->send('http://g.apibus.io', $data, $headers)){
return false;
}
if (isset($ret['ApiBusError'])) {
trace('errno:' . $ret['ApiBusError']['errcode'] . ',errmsg:' . $ret['ApiBusError']['errdesc'], '升级通知出错', 'NOTIC', true);
return false;
}
return true;
}
private function send($url, $params = array() , $headers = array()) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if (!empty($params)) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
}
if (!empty($headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$txt = curl_exec($ch);
if (curl_errno($ch)) {
trace(curl_error($ch) , '升级通知出错', 'NOTIC', true);
return false;
}
curl_close($ch);
$ret = json_decode($txt, true);
if (!$ret) {
trace('接口[' . $url . ']返回格式不正确', '升级通知出错', 'NOTIC', true);
return false;
}
return $ret;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Apachenote缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver
* @author liu21st <liu21st@gmail.com>
*/
class CacheApachenote extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if(!empty($options)) {
$this->options = $options;
}
if(empty($options)) {
$options = array (
'host' => '127.0.0.1',
'port' => 1042,
'timeout' => 10,
);
}
$this->options = $options;
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$this->handler = null;
$this->open();
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
$this->open();
$name = $this->options['prefix'].$name;
$s = 'F' . pack('N', strlen($name)) . $name;
fwrite($this->handler, $s);
for ($data = ''; !feof($this->handler);) {
$data .= fread($this->handler, 4096);
}
N('cache_read',1);
$this->close();
return $data === '' ? '' : unserialize($data);
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @return boolen
*/
public function set($name, $value) {
N('cache_write',1);
$this->open();
$value = serialize($value);
$name = $this->options['prefix'].$name;
$s = 'S' . pack('NN', strlen($name), strlen($value)) . $name . $value;
fwrite($this->handler, $s);
$ret = fgets($this->handler);
$this->close();
if($ret === "OK\n") {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
$this->open();
$name = $this->options['prefix'].$name;
$s = 'D' . pack('N', strlen($name)) . $name;
fwrite($this->handler, $s);
$ret = fgets($this->handler);
$this->close();
return $ret === "OK\n";
}
/**
* 关闭缓存
* @access private
*/
private function close() {
fclose($this->handler);
$this->handler = false;
}
/**
* 打开缓存
* @access private
*/
private function open() {
if (!is_resource($this->handler)) {
$this->handler = fsockopen($this->options['host'], $this->options['port'], $_, $_, $this->options['timeout']);
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Apc缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheApc extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if(!function_exists('apc_cache_info')) {
throw_exception(L('_NOT_SUPPERT_').':Apc');
}
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
return apc_fetch($this->options['prefix'].$name);
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value, $expire = null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$name = $this->options['prefix'].$name;
if($result = apc_store($name, $value, $expire)) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
}
return $result;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
return apc_delete($this->options['prefix'].$name);
}
/**
* 清除缓存
* @access public
* @return boolen
*/
public function clear() {
return apc_clear_cache();
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 数据库方式缓存驱动
* CREATE TABLE think_cache (
* cachekey varchar(255) NOT NULL,
* expire int(11) NOT NULL,
* data blob,
* datacrc int(32),
* UNIQUE KEY `cachekey` (`cachekey`)
* );
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheDb extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if(empty($options)) {
$options = array (
'table' => C('DATA_CACHE_TABLE'),
);
}
$this->options = $options;
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
import('Db');
$this->handler = DB::getInstance();
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
$name = $this->options['prefix'].addslashes($name);
N('cache_read',1);
$result = $this->handler->query('SELECT `data`,`datacrc` FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$name.'\' AND (`expire` =0 OR `expire`>'.time().') LIMIT 0,1');
if(false !== $result ) {
$result = $result[0];
if(C('DATA_CACHE_CHECK')) {//开启数据校验
if($result['datacrc'] != md5($result['data'])) {//校验错误
return false;
}
}
$content = $result['data'];
if(C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//启用数据压缩
$content = gzuncompress($content);
}
$content = unserialize($content);
return $content;
}
else {
return false;
}
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value,$expire=null) {
$data = serialize($value);
$name = $this->options['prefix'].addslashes($name);
N('cache_write',1);
if( C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//数据压缩
$data = gzcompress($data,3);
}
if(C('DATA_CACHE_CHECK')) {//开启数据校验
$crc = md5($data);
}else {
$crc = '';
}
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$expire = ($expire==0)?0: (time()+$expire) ;//缓存有效期为0表示永久缓存
$result = $this->handler->query('select `cachekey` from `'.$this->options['table'].'` where `cachekey`=\''.$name.'\' limit 0,1');
if(!empty($result) ) {
//更新记录
$result = $this->handler->execute('UPDATE '.$this->options['table'].' SET data=\''.$data.'\' ,datacrc=\''.$crc.'\',expire='.$expire.' WHERE `cachekey`=\''.$name.'\'');
}else {
//新增记录
$result = $this->handler->execute('INSERT INTO '.$this->options['table'].' (`cachekey`,`data`,`datacrc`,`expire`) VALUES (\''.$name.'\',\''.$data.'\',\''.$crc.'\','.$expire.')');
}
if($result) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}else {
return false;
}
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
$name = $this->options['prefix'].addslashes($name);
return $this->handler->execute('DELETE FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$name.'\'');
}
/**
* 清除缓存
* @access public
* @return boolen
*/
public function clear() {
return $this->handler->execute('TRUNCATE TABLE `'.$this->options['table'].'`');
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Eaccelerator缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheEaccelerator extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
return eaccelerator_get($this->options['prefix'].$name);
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value, $expire = null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$name = $this->options['prefix'].$name;
eaccelerator_lock($name);
if(eaccelerator_put($name, $value, $expire)) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
return eaccelerator_rm($this->options['prefix'].$name);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Memcache缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheMemcache extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
function __construct($options=array()) {
if ( !extension_loaded('memcache') ) {
throw_exception(L('_NOT_SUPPERT_').':memcache');
}
$options = array_merge(array (
'host' => C('MEMCACHE_HOST') ? C('MEMCACHE_HOST') : '127.0.0.1',
'port' => C('MEMCACHE_PORT') ? C('MEMCACHE_PORT') : 11211,
'timeout' => C('DATA_CACHE_TIMEOUT') ? C('DATA_CACHE_TIMEOUT') : false,
'persistent' => false,
),$options);
$this->options = $options;
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$func = $options['persistent'] ? 'pconnect' : 'connect';
$this->handler = new Memcache;
$options['timeout'] === false ?
$this->handler->$func($options['host'], $options['port']) :
$this->handler->$func($options['host'], $options['port'], $options['timeout']);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
return $this->handler->get($this->options['prefix'].$name);
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value, $expire = null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$name = $this->options['prefix'].$name;
if($this->handler->set($name, $value, 0, $expire)) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name, $ttl = false) {
$name = $this->options['prefix'].$name;
return $ttl === false ?
$this->handler->delete($name) :
$this->handler->delete($name, $ttl);
}
/**
* 清除缓存
* @access public
* @return boolen
*/
public function clear() {
return $this->handler->flush();
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Redis缓存驱动
* 要求安装phpredis扩展:https://github.com/nicolasff/phpredis
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author 尘缘 <130775@qq.com>
*/
class CacheRedis extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if ( !extension_loaded('redis') ) {
throw_exception(L('_NOT_SUPPERT_').':redis');
}
if(empty($options)) {
$options = array (
'host' => C('REDIS_HOST') ? C('REDIS_HOST') : '127.0.0.1',
'port' => C('REDIS_PORT') ? C('REDIS_PORT') : 6379,
'timeout' => C('DATA_CACHE_TIMEOUT') ? C('DATA_CACHE_TIMEOUT') : false,
'persistent' => false,
);
}
$this->options = $options;
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$func = $options['persistent'] ? 'pconnect' : 'connect';
$this->handler = new Redis;
$options['timeout'] === false ?
$this->handler->$func($options['host'], $options['port']) :
$this->handler->$func($options['host'], $options['port'], $options['timeout']);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
$value = $this->handler->get($this->options['prefix'].$name);
$jsonData = json_decode( $value, true );
return ($jsonData === NULL) ? $value : $jsonData; //检测是否为JSON数据 true 返回JSON解析数组, false返回源数据
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value, $expire = null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$name = $this->options['prefix'].$name;
//对数组/对象数据进行缓存处理,保证数据完整性
$value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
if(is_int($expire)) {
$result = $this->handler->setex($name, $expire, $value);
}else{
$result = $this->handler->set($name, $value);
}
if($result && $this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return $result;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
return $this->handler->delete($this->options['prefix'].$name);
}
/**
* 清除缓存
* @access public
* @return boolen
*/
public function clear() {
return $this->handler->flushDB();
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Shmop缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheShmop extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if ( !extension_loaded('shmop') ) {
throw_exception(L('_NOT_SUPPERT_').':shmop');
}
if(!empty($options)){
$options = array(
'size' => C('SHARE_MEM_SIZE'),
'temp' => TEMP_PATH,
'project' => 's',
'length' => 0,
);
}
$this->options = $options;
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$this->handler = $this->_ftok($this->options['project']);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name = false) {
N('cache_read',1);
$id = shmop_open($this->handler, 'c', 0600, 0);
if ($id !== false) {
$ret = unserialize(shmop_read($id, 0, shmop_size($id)));
shmop_close($id);
if ($name === false) {
return $ret;
}
$name = $this->options['prefix'].$name;
if(isset($ret[$name])) {
$content = $ret[$name];
if(C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//启用数据压缩
$content = gzuncompress($content);
}
return $content;
}else {
return null;
}
}else {
return false;
}
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @return boolen
*/
public function set($name, $value) {
N('cache_write',1);
$lh = $this->_lock();
$val = $this->get();
if (!is_array($val)) $val = array();
if( C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//数据压缩
$value = gzcompress($value,3);
}
$name = $this->options['prefix'].$name;
$val[$name] = $value;
$val = serialize($val);
if($this->_write($val, $lh)) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
$lh = $this->_lock();
$val = $this->get();
if (!is_array($val)) $val = array();
$name = $this->options['prefix'].$name;
unset($val[$name]);
$val = serialize($val);
return $this->_write($val, $lh);
}
/**
* 生成IPC key
* @access private
* @param string $project 项目标识名
* @return integer
*/
private function _ftok($project) {
if (function_exists('ftok')) return ftok(__FILE__, $project);
if(strtoupper(PHP_OS) == 'WINNT'){
$s = stat(__FILE__);
return sprintf("%u", (($s['ino'] & 0xffff) | (($s['dev'] & 0xff) << 16) |
(($project & 0xff) << 24)));
}else {
$filename = __FILE__ . (string) $project;
for($key = array(); sizeof($key) < strlen($filename); $key[] = ord(substr($filename, sizeof($key), 1)));
return dechex(array_sum($key));
}
}
/**
* 写入操作
* @access private
* @param string $name 缓存变量名
* @return integer|boolen
*/
private function _write(&$val, &$lh) {
$id = shmop_open($this->handler, 'c', 0600, $this->options['size']);
if ($id) {
$ret = shmop_write($id, $val, 0) == strlen($val);
shmop_close($id);
$this->_unlock($lh);
return $ret;
}
$this->_unlock($lh);
return false;
}
/**
* 共享锁定
* @access private
* @param string $name 缓存变量名
* @return boolen
*/
private function _lock() {
if (function_exists('sem_get')) {
$fp = sem_get($this->handler, 1, 0600, 1);
sem_acquire ($fp);
} else {
$fp = fopen($this->options['temp'].$this->options['prefix'].md5($this->handler), 'w');
flock($fp, LOCK_EX);
}
return $fp;
}
/**
* 解除共享锁定
* @access private
* @param string $name 缓存变量名
* @return boolen
*/
private function _unlock(&$fp) {
if (function_exists('sem_release')) {
sem_release($fp);
} else {
fclose($fp);
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Sqlite缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheSqlite extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if ( !extension_loaded('sqlite') ) {
throw_exception(L('_NOT_SUPPERT_').':sqlite');
}
if(empty($options)) {
$options = array (
'db' => ':memory:',
'table' => 'sharedmemory',
);
}
$this->options = $options;
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
$func = $this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open';
$this->handler = $func($this->options['db']);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
$name = $this->options['prefix'].sqlite_escape_string($name);
$sql = 'SELECT value FROM '.$this->options['table'].' WHERE var=\''.$name.'\' AND (expire=0 OR expire >'.time().') LIMIT 1';
$result = sqlite_query($this->handler, $sql);
if (sqlite_num_rows($result)) {
$content = sqlite_fetch_single($result);
if(C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//启用数据压缩
$content = gzuncompress($content);
}
return unserialize($content);
}
return false;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value,$expire=null) {
N('cache_write',1);
$name = $this->options['prefix'].sqlite_escape_string($name);
$value = sqlite_escape_string(serialize($value));
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$expire = ($expire==0)?0: (time()+$expire) ;//缓存有效期为0表示永久缓存
if( C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//数据压缩
$value = gzcompress($value,3);
}
$sql = 'REPLACE INTO '.$this->options['table'].' (var, value,expire) VALUES (\''.$name.'\', \''.$value.'\', \''.$expire.'\')';
if(sqlite_query($this->handler, $sql)){
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
$name = $this->options['prefix'].sqlite_escape_string($name);
$sql = 'DELETE FROM '.$this->options['table'].' WHERE var=\''.$name.'\'';
sqlite_query($this->handler, $sql);
return true;
}
/**
* 清除缓存
* @access public
* @return boolen
*/
public function clear() {
$sql = 'DELETE FROM '.$this->options['table'];
sqlite_query($this->handler, $sql);
return ;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Wincache缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheWincache extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if ( !function_exists('wincache_ucache_info') ) {
throw_exception(L('_NOT_SUPPERT_').':WinCache');
}
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
$name = $this->options['prefix'].$name;
return wincache_ucache_exists($name)? wincache_ucache_get($name) : false;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value,$expire=null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$name = $this->options['prefix'].$name;
if(wincache_ucache_set($name, $value, $expire)) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
return wincache_ucache_delete($this->options['prefix'].$name);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Xcache缓存驱动
* @category Extend
* @package Extend
* @subpackage Driver.Cache
* @author liu21st <liu21st@gmail.com>
*/
class CacheXcache extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if ( !function_exists('xcache_info') ) {
throw_exception(L('_NOT_SUPPERT_').':Xcache');
}
$this->options['expire'] = isset($options['expire'])?$options['expire']:C('DATA_CACHE_TIME');
$this->options['prefix'] = isset($options['prefix'])?$options['prefix']:C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])?$options['length']:0;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
$name = $this->options['prefix'].$name;
if (xcache_isset($name)) {
return xcache_get($name);
}
return false;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolen
*/
public function set($name, $value,$expire=null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'] ;
}
$name = $this->options['prefix'].$name;
if(xcache_set($name, $value, $expire)) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return true;
}
return false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolen
*/
public function rm($name) {
return xcache_unset($this->options['prefix'].$name);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Firebird数据库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author 剑雷
*/
class DbIbase extends Db{
protected $selectSql = 'SELECT %LIMIT% %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%';
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config='') {
if ( !extension_loaded('interbase') ) {
throw_exception(L('_NOT_SUPPERT_').':Interbase or Firebird');
}
if(!empty($config)) {
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
* @throws ThinkExecption
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
$conn = $pconnect ? 'ibase_pconnect':'ibase_connect';
// 处理不带端口号的socket连接情况
$host = $config['hostname'].($config['hostport']?"/{$config['hostport']}":'');
$this->linkID[$linkNum] = $conn($host.':'.$config['database'], $config['username'], $config['password'],C('DB_CHARSET'),0,3);
if ( !$this->linkID[$linkNum]) {
throw_exception(ibase_errmsg());
}
// 标记连接成功
$this->connected = true;
// 注销数据库连接配置信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
ibase_free_result($this->queryID);
$this->queryID = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @return mixed
*/
public function query($str) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$this->queryID = ibase_query($this->_linkID, $str);
$this->debug();
if ( false === $this->queryID ) {
$this->error();
return false;
} else {
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @return integer
*/
public function execute($str) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$result = ibase_query($this->_linkID, $str) ;
$this->debug();
if ( false === $result) {
$this->error();
return false;
} else {
$this->numRows = ibase_affected_rows($this->_linkID);
$this->lastInsID =0;
return $this->numRows;
}
}
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
ibase_trans( IBASE_DEFAULT, $this->_linkID);
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit() {
if ($this->transTimes > 0) {
$result = ibase_commit($this->_linkID);
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback() {
if ($this->transTimes > 0) {
$result =ibase_rollback($this->_linkID);
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* BLOB字段解密函数 Firebird特有
* @access public
* @param $blob 待解密的BLOB
* @return 二进制数据
*/
public function BlobDecode($blob) {
$maxblobsize = 262144;
$blob_data = ibase_blob_info($this->_linkID, $blob );
$blobid = ibase_blob_open($this->_linkID, $blob );
if( $blob_data[0] > $maxblobsize ) {
$realblob = ibase_blob_get($blobid, $maxblobsize);
while($string = ibase_blob_get($blobid, 8192)){
$realblob .= $string;
}
} else {
$realblob = ibase_blob_get($blobid, $blob_data[0]);
}
ibase_blob_close( $blobid );
return( $realblob );
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = array();
while ( $row = ibase_fetch_assoc($this->queryID)) {
$result[] = $row;
}
//剑雷 2007.12.30 自动解密BLOB字段
//取BLOB字段清单
$bloblist = array();
$fieldCount = ibase_num_fields($this->queryID);
for ($i = 0; $i < $fieldCount; $i++) {
$col_info = ibase_field_info($this->queryID, $i);
if ($col_info['type']=='BLOB') {
$bloblist[]=trim($col_info['name']);
}
}
//如果有BLOB字段,就进行解密处理
if (!empty($bloblist)) {
$i=0;
foreach ($result as $row) {
foreach($bloblist as $field) {
if (!empty($row[$field])) $result[$i][$field]=$this->BlobDecode($row[$field]);
}
$i++;
}
}
return $result;
}
/**
* 取得数据表的字段信息
* @access public
*/
public function getFields($tableName) {
$result = $this->query('SELECT RDB$FIELD_NAME AS FIELD, RDB$DEFAULT_VALUE AS DEFAULT1, RDB$NULL_FLAG AS NULL1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME=UPPER(\''.$tableName.'\') ORDER By RDB$FIELD_POSITION');
$info = array();
if($result) {
foreach ($result as $key => $val) {
$info[trim($val['FIELD'])] = array(
'name' => trim($val['FIELD']),
'type' => '',
'notnull' => (bool) ($val['NULL1'] ==1), // 1表示不为Null
'default' => $val['DEFAULT1'],
'primary' => false,
'autoinc' => false,
);
}
}
//剑雷 取表字段类型
$sql='select first 1 * from '. $tableName;
$rs_temp = ibase_query ($this->_linkID, $sql);
$fieldCount = ibase_num_fields($rs_temp);
for ($i = 0; $i < $fieldCount; $i++)
{
$col_info = ibase_field_info($rs_temp, $i);
$info[trim($col_info['name'])]['type']=$col_info['type'];
}
ibase_free_result ($rs_temp);
//剑雷 取表的主键
$sql='select b.rdb$field_name as FIELD_NAME from rdb$relation_constraints a join rdb$index_segments b
on a.rdb$index_name=b.rdb$index_name
where a.rdb$constraint_type=\'PRIMARY KEY\' and a.rdb$relation_name=UPPER(\''.$tableName.'\')';
$rs_temp = ibase_query ($this->_linkID, $sql);
while ($row=ibase_fetch_object($rs_temp)) {
$info[trim($row->FIELD_NAME)]['primary']=True;
}
ibase_free_result ($rs_temp);
return $info;
}
/**
* 取得数据库的表信息
* @access public
*/
public function getTables($dbName='') {
$sql='SELECT DISTINCT RDB$RELATION_NAME FROM RDB$RELATION_FIELDS WHERE RDB$SYSTEM_FLAG=0';
$result = $this->query($sql);
$info = array();
foreach ($result as $key => $val) {
$info[$key] = trim(current($val));
}
return $info;
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if ($this->_linkID){
ibase_close($this->_linkID);
}
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error() {
$this->error = ibase_errcode().':'.ibase_errmsg();
if('' != $this->queryStr){
$this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
}
trace($this->error,'','ERR');
return $this->error;
}
/**
* SQL指令安全过滤
* @access public
* @param string $str SQL指令
* @return string
*/
public function escapeString($str) {
return str_replace("'", "''", $str);
}
/**
* limit
* @access public
* @param $limit limit表达式
* @return string
*/
public function parseLimit($limit) {
$limitStr = '';
if(!empty($limit)) {
$limit = explode(',',$limit);
if(count($limit)>1) {
$limitStr = ' FIRST '.($limit[1]-$limit[0]).' SKIP '.$limit[0].' ';
}else{
$limitStr = ' FIRST '.$limit[0].' ';
}
}
return $limitStr;
}
}
<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Mongo数据库驱动 必须配合MongoModel使用
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author liu21st <liu21st@gmail.com>
*/
class DbMongo extends Db{
protected $_mongo = null; // MongoDb Object
protected $_collection = null; // MongoCollection Object
protected $_dbName = ''; // dbName
protected $_collectionName = ''; // collectionName
protected $_cursor = null; // MongoCursor Object
protected $comparison = array('neq'=>'ne','ne'=>'ne','gt'=>'gt','egt'=>'gte','gte'=>'gte','lt'=>'lt','elt'=>'lte','lte'=>'lte','in'=>'in','not in'=>'nin','nin'=>'nin');
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config=''){
if ( !class_exists('mongoClient') ) {
throw_exception(L('_NOT_SUPPERT_').':mongoClient');
}
if(!empty($config)) {
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$host = 'mongodb://'.($config['username']?"{$config['username']}":'').($config['password']?":{$config['password']}@":'').$config['hostname'].($config['hostport']?":{$config['hostport']}":'').'/'.($config['database']?"{$config['database']}":'');
try{
$this->linkID[$linkNum] = new mongoClient( $host,$config['params']);
}catch (MongoConnectionException $e){
throw_exception($e->getmessage());
}
// 标记连接成功
$this->connected = true;
// 注销数据库连接配置信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 切换当前操作的Db和Collection
* @access public
* @param string $collection collection
* @param string $db db
* @param boolean $master 是否主服务器
* @return void
*/
public function switchCollection($collection,$db='',$master=true){
// 当前没有连接 则首先进行数据库连接
if ( !$this->_linkID ) $this->initConnect($master);
try{
if(!empty($db)) { // 传人Db则切换数据库
// 当前MongoDb对象
$this->_dbName = $db;
$this->_mongo = $this->_linkID->selectDb($db);
}
// 当前MongoCollection对象
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.getCollection('.$collection.')';
}
if($this->_collectionName != $collection) {
N('db_read',1);
// 记录开始执行时间
G('queryStartTime');
$this->_collection = $this->_mongo->selectCollection($collection);
$this->debug();
$this->_collectionName = $collection; // 记录当前Collection名称
}
}catch (MongoException $e){
throw_exception($e->getMessage());
}
}
/**
* 释放查询结果
* @access public
*/
public function free() {
$this->_cursor = null;
}
/**
* 执行命令
* @access public
* @param array $command 指令
* @return array
*/
public function command($command=array()) {
N('db_write',1);
$this->queryStr = 'command:'.json_encode($command);
// 记录开始执行时间
G('queryStartTime');
$result = $this->_mongo->command($command);
$this->debug();
if(!$result['ok']) {
throw_exception($result['errmsg']);
}
return $result;
}
/**
* 执行语句
* @access public
* @param string $code sql指令
* @param array $args 参数
* @return mixed
*/
public function execute($code,$args=array()) {
N('db_write',1);
$this->queryStr = 'execute:'.$code;
// 记录开始执行时间
G('queryStartTime');
$result = $this->_mongo->execute($code,$args);
$this->debug();
if($result['ok']) {
return $result['retval'];
}else{
throw_exception($result['errmsg']);
}
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if($this->_linkID) {
$this->_linkID->close();
$this->_linkID = null;
$this->_mongo = null;
$this->_collection = null;
$this->_cursor = null;
}
}
/**
* 数据库错误信息
* @access public
* @return string
*/
public function error() {
$this->error = $this->_mongo->lastError();
trace($this->error,'','ERR');
return $this->error;
}
/**
* 插入记录
* @access public
* @param mixed $data 数据
* @param array $options 参数表达式
* @param boolean $replace 是否replace
* @return false | integer
*/
public function insert($data,$options=array(),$replace=false) {
if(isset($options['table'])) {
$this->switchCollection($options['table']);
}
$this->model = $options['model'];
N('db_write',1);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.insert(';
$this->queryStr .= $data?json_encode($data):'{}';
$this->queryStr .= ')';
}
try{
// 记录开始执行时间
G('queryStartTime');
$result = $replace? $this->_collection->save($data): $this->_collection->insert($data);
$this->debug();
if($result) {
$_id = $data['_id'];
if(is_object($_id)) {
$_id = $_id->__toString();
}
$this->lastInsID = $_id;
}
return $result;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 插入多条记录
* @access public
* @param array $dataList 数据
* @param array $options 参数表达式
* @return bool
*/
public function insertAll($dataList,$options=array()) {
if(isset($options['table'])) {
$this->switchCollection($options['table']);
}
$this->model = $options['model'];
N('db_write',1);
try{
// 记录开始执行时间
G('queryStartTime');
$result = $this->_collection->batchInsert($dataList);
$this->debug();
return $result;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 生成下一条记录ID 用于自增非MongoId主键
* @access public
* @param string $pk 主键名
* @return integer
*/
public function mongo_next_id($pk) {
N('db_read',1);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.find({},{'.$pk.':1}).sort({'.$pk.':-1}).limit(1)';
}
try{
// 记录开始执行时间
G('queryStartTime');
$result = $this->_collection->find(array(),array($pk=>1))->sort(array($pk=>-1))->limit(1);
$this->debug();
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
$data = $result->getNext();
return isset($data[$pk])?$data[$pk]+1:1;
}
/**
* 更新记录
* @access public
* @param mixed $data 数据
* @param array $options 表达式
* @return bool
*/
public function update($data,$options) {
if(isset($options['table'])) {
$this->switchCollection($options['table']);
}
$this->model = $options['model'];
N('db_write',1);
$query = $this->parseWhere($options['where']);
$set = $this->parseSet($data);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.update(';
$this->queryStr .= $query?json_encode($query):'{}';
$this->queryStr .= ','.json_encode($set).')';
}
try{
// 记录开始执行时间
G('queryStartTime');
if(isset($options['limit']) && $options['limit'] == 1) {
$multiple = array("multiple" => false);
}else{
$multiple = array("multiple" => true);
}
$result = $this->_collection->update($query,$set,$multiple);
$this->debug();
return $result;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 删除记录
* @access public
* @param array $options 表达式
* @return false | integer
*/
public function delete($options=array()) {
if(isset($options['table'])) {
$this->switchCollection($options['table']);
}
$query = $this->parseWhere($options['where']);
$this->model = $options['model'];
N('db_write',1);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.remove('.json_encode($query).')';
}
try{
// 记录开始执行时间
G('queryStartTime');
$result = $this->_collection->remove($query);
$this->debug();
return $result;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 清空记录
* @access public
* @param array $options 表达式
* @return false | integer
*/
public function clear($options=array()){
if(isset($options['table'])) {
$this->switchCollection($options['table']);
}
$this->model = $options['model'];
N('db_write',1);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.remove({})';
}
try{
// 记录开始执行时间
G('queryStartTime');
$result = $this->_collection->drop();
$this->debug();
return $result;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 查找记录
* @access public
* @param array $options 表达式
* @return iterator
*/
public function select($options=array()) {
if(isset($options['table'])) {
$this->switchCollection($options['table'],'',false);
}
$cache = isset($options['cache'])?$options['cache']:false;
if($cache) { // 查询缓存检测
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
$value = S($key,'','',$cache['type']);
if(false !== $value) {
return $value;
}
}
$this->model = $options['model'];
N('db_query',1);
$query = $this->parseWhere($options['where']);
$field = $this->parseField($options['field']);
try{
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.find(';
$this->queryStr .= $query? json_encode($query):'{}';
$this->queryStr .= $field? ','.json_encode($field):'';
$this->queryStr .= ')';
}
// 记录开始执行时间
G('queryStartTime');
$_cursor = $this->_collection->find($query,$field);
if($options['order']) {
$order = $this->parseOrder($options['order']);
if(C('DB_SQL_LOG')) {
$this->queryStr .= '.sort('.json_encode($order).')';
}
$_cursor = $_cursor->sort($order);
}
if(isset($options['page'])) { // 根据页数计算limit
if(strpos($options['page'],',')) {
list($page,$length) = explode(',',$options['page']);
}else{
$page = $options['page'];
}
$page = $page?$page:1;
$length = isset($length)?$length:(is_numeric($options['limit'])?$options['limit']:20);
$offset = $length*((int)$page-1);
$options['limit'] = $offset.','.$length;
}
if(isset($options['limit'])) {
list($offset,$length) = $this->parseLimit($options['limit']);
if(!empty($offset)) {
if(C('DB_SQL_LOG')) {
$this->queryStr .= '.skip('.intval($offset).')';
}
$_cursor = $_cursor->skip(intval($offset));
}
if(C('DB_SQL_LOG')) {
$this->queryStr .= '.limit('.intval($length).')';
}
$_cursor = $_cursor->limit(intval($length));
}
$this->debug();
$this->_cursor = $_cursor;
$resultSet = iterator_to_array($_cursor);
if($cache && $resultSet ) { // 查询缓存写入
S($key,$resultSet,$cache['expire'],$cache['type']);
}
return $resultSet;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 查找某个记录
* @access public
* @param array $options 表达式
* @return array
*/
public function find($options=array()){
if(isset($options['table'])) {
$this->switchCollection($options['table'],'',false);
}
$cache = isset($options['cache'])?$options['cache']:false;
if($cache) { // 查询缓存检测
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
$value = S($key,'','',$cache['type']);
if(false !== $value) {
return $value;
}
}
$this->model = $options['model'];
N('db_query',1);
$query = $this->parseWhere($options['where']);
$fields = $this->parseField($options['field']);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.findOne(';
$this->queryStr .= $query?json_encode($query):'{}';
$this->queryStr .= $fields?','.json_encode($fields):'';
$this->queryStr .= ')';
}
try{
// 记录开始执行时间
G('queryStartTime');
$result = $this->_collection->findOne($query,$fields);
$this->debug();
if($cache && $result ) { // 查询缓存写入
S($key,$result,$cache['expire'],$cache['type']);
}
return $result;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
/**
* 统计记录数
* @access public
* @param array $options 表达式
* @return iterator
*/
public function count($options=array()){
if(isset($options['table'])) {
$this->switchCollection($options['table'],'',false);
}
$this->model = $options['model'];
N('db_query',1);
$query = $this->parseWhere($options['where']);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName;
$this->queryStr .= $query?'.find('.json_encode($query).')':'';
$this->queryStr .= '.count()';
}
try{
// 记录开始执行时间
G('queryStartTime');
$count = $this->_collection->count($query);
$this->debug();
return $count;
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
}
public function group($keys,$initial,$reduce,$options=array()){
$this->_collection->group($keys,$initial,$reduce,$options);
}
/**
* 取得数据表的字段信息
* @access public
* @return array
*/
public function getFields($collection=''){
if(!empty($collection) && $collection != $this->_collectionName) {
$this->switchCollection($collection,'',false);
}
N('db_query',1);
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.findOne()';
}
try{
// 记录开始执行时间
G('queryStartTime');
$result = $this->_collection->findOne();
$this->debug();
} catch (MongoCursorException $e) {
throw_exception($e->getMessage());
}
if($result) { // 存在数据则分析字段
$info = array();
foreach ($result as $key=>$val){
$info[$key] = array(
'name'=>$key,
'type'=>getType($val),
);
}
return $info;
}
// 暂时没有数据 返回false
return false;
}
/**
* 取得当前数据库的collection信息
* @access public
*/
public function getTables(){
if(C('DB_SQL_LOG')) {
$this->queryStr = $this->_dbName.'.getCollenctionNames()';
}
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$list = $this->_mongo->listCollections();
$this->debug();
$info = array();
foreach ($list as $collection){
$info[] = $collection->getName();
}
return $info;
}
/**
* set分析
* @access protected
* @param array $data
* @return string
*/
protected function parseSet($data) {
$result = array();
foreach ($data as $key=>$val){
if(is_array($val)) {
switch($val[0]) {
case 'inc':
$result['$inc'][$key] = (int)$val[1];
break;
case 'set':
case 'unset':
case 'push':
case 'pushall':
case 'addtoset':
case 'pop':
case 'pull':
case 'pullall':
$result['$'.$val[0]][$key] = $val[1];
break;
default:
$result['$set'][$key] = $val;
}
}else{
$result['$set'][$key] = $val;
}
}
return $result;
}
/**
* order分析
* @access protected
* @param mixed $order
* @return array
*/
protected function parseOrder($order) {
if(is_string($order)) {
$array = explode(',',$order);
$order = array();
foreach ($array as $key=>$val){
$arr = explode(' ',trim($val));
if(isset($arr[1])) {
$arr[1] = $arr[1]=='asc'?1:-1;
}else{
$arr[1] = 1;
}
$order[$arr[0]] = $arr[1];
}
}
return $order;
}
/**
* limit分析
* @access protected
* @param mixed $limit
* @return array
*/
protected function parseLimit($limit) {
if(strpos($limit,',')) {
$array = explode(',',$limit);
}else{
$array = array(0,$limit);
}
return $array;
}
/**
* field分析
* @access protected
* @param mixed $fields
* @return array
*/
public function parseField($fields){
if(empty($fields)) {
$fields = array();
}
if(is_string($fields)) {
$fields = explode(',',$fields);
}
return $fields;
}
/**
* where分析
* @access protected
* @param mixed $where
* @return array
*/
public function parseWhere($where){
$query = array();
foreach ($where as $key=>$val){
if('_id' != $key && 0===strpos($key,'_')) {
// 解析特殊条件表达式
$query = $this->parseThinkWhere($key,$val);
}else{
// 查询字段的安全过滤
if(!preg_match('/^[A-Z_\|\&\-.a-z0-9]+$/',trim($key))){
throw_exception(L('_ERROR_QUERY_').':'.$key);
}
$key = trim($key);
if(strpos($key,'|')) {
$array = explode('|',$key);
$str = array();
foreach ($array as $k){
$str[] = $this->parseWhereItem($k,$val);
}
$query['$or'] = $str;
}elseif(strpos($key,'&')){
$array = explode('&',$key);
$str = array();
foreach ($array as $k){
$str[] = $this->parseWhereItem($k,$val);
}
$query = array_merge($query,$str);
}else{
$str = $this->parseWhereItem($key,$val);
$query = array_merge($query,$str);
}
}
}
return $query;
}
/**
* 特殊条件分析
* @access protected
* @param string $key
* @param mixed $val
* @return string
*/
protected function parseThinkWhere($key,$val) {
$query = array();
switch($key) {
case '_query': // 字符串模式查询条件
parse_str($val,$query);
if(isset($query['_logic']) && strtolower($query['_logic']) == 'or' ) {
unset($query['_logic']);
$query['$or'] = $query;
}
break;
case '_string':// MongoCode查询
$query['$where'] = new MongoCode($val);
break;
}
return $query;
}
/**
* where子单元分析
* @access protected
* @param string $key
* @param mixed $val
* @return array
*/
protected function parseWhereItem($key,$val) {
$query = array();
if(is_array($val)) {
if(is_string($val[0])) {
$con = strtolower($val[0]);
if(in_array($con,array('neq','ne','gt','egt','gte','lt','lte','elt'))) { // 比较运算
$k = '$'.$this->comparison[$con];
$query[$key] = array($k=>$val[1]);
}elseif('like'== $con){ // 模糊查询 采用正则方式
$query[$key] = new MongoRegex("/".$val[1]."/");
}elseif('mod'==$con){ // mod 查询
$query[$key] = array('$mod'=>$val[1]);
}elseif('regex'==$con){ // 正则查询
$query[$key] = new MongoRegex($val[1]);
}elseif(in_array($con,array('in','nin','not in'))){ // IN NIN 运算
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$k = '$'.$this->comparison[$con];
$query[$key] = array($k=>$data);
}elseif('all'==$con){ // 满足所有指定条件
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$query[$key] = array('$all'=>$data);
}elseif('between'==$con){ // BETWEEN运算
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$query[$key] = array('$gte'=>$data[0],'$lte'=>$data[1]);
}elseif('not between'==$con){
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$query[$key] = array('$lt'=>$data[0],'$gt'=>$data[1]);
}elseif('exp'==$con){ // 表达式查询
$query['$where'] = new MongoCode($val[1]);
}elseif('exists'==$con){ // 字段是否存在
$query[$key] =array('$exists'=>(bool)$val[1]);
}elseif('size'==$con){ // 限制属性大小
$query[$key] =array('$size'=>intval($val[1]));
}elseif('type'==$con){ // 限制字段类型 1 浮点型 2 字符型 3 对象或者MongoDBRef 5 MongoBinData 7 MongoId 8 布尔型 9 MongoDate 10 NULL 15 MongoCode 16 32位整型 17 MongoTimestamp 18 MongoInt64 如果是数组的话判断元素的类型
$query[$key] =array('$type'=>intval($val[1]));
}else{
$query[$key] = $val;
}
return $query;
}
}
$query[$key] = $val;
return $query;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* MSsql数据库驱动 要求sqlserver2005
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author liu21st <liu21st@gmail.com>
*/
class DbMssql extends Db{
protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%';
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config=''){
if ( !function_exists('mssql_connect') ) {
throw_exception(L('_NOT_SUPPERT_').':mssql');
}
if(!empty($config)) {
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
$conn = $pconnect ? 'mssql_pconnect':'mssql_connect';
// 处理不带端口号的socket连接情况
$sepr = IS_WIN ? ',' : ':';
$host = $config['hostname'].($config['hostport']?$sepr."{$config['hostport']}":'');
$this->linkID[$linkNum] = $conn( $host, $config['username'], $config['password']);
if ( !$this->linkID[$linkNum] ) throw_exception("Couldn't connect to SQL Server on $host");
if ( !empty($config['database']) && !mssql_select_db($config['database'], $this->linkID[$linkNum]) ) {
throw_exception("Couldn't open database '".$config['database']);
}
// 标记连接成功
$this->connected = true;
//注销数据库安全信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
mssql_free_result($this->queryID);
$this->queryID = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @return mixed
*/
public function query($str) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$this->queryID = mssql_query($str, $this->_linkID);
$this->debug();
if ( false === $this->queryID ) {
$this->error();
return false;
} else {
$this->numRows = mssql_num_rows($this->queryID);
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @return integer
*/
public function execute($str) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$result = mssql_query($str, $this->_linkID);
$this->debug();
if ( false === $result ) {
$this->error();
return false;
} else {
$this->numRows = mssql_rows_affected($this->_linkID);
$this->lastInsID = $this->mssql_insert_id();
return $this->numRows;
}
}
/**
* 用于获取最后插入的ID
* @access public
* @return integer
*/
public function mssql_insert_id() {
$query = "SELECT @@IDENTITY as last_insert_id";
$result = mssql_query($query, $this->_linkID);
list($last_insert_id) = mssql_fetch_row($result);
mssql_free_result($result);
return $last_insert_id;
}
/**
* 启动事务
* @access public
* @return void
*/
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
mssql_query('BEGIN TRAN', $this->_linkID);
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit() {
if ($this->transTimes > 0) {
$result = mssql_query('COMMIT TRAN', $this->_linkID);
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback() {
if ($this->transTimes > 0) {
$result = mssql_query('ROLLBACK TRAN', $this->_linkID);
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = array();
if($this->numRows >0) {
while($row = mssql_fetch_assoc($this->queryID))
$result[] = $row;
}
return $result;
}
/**
* 取得数据表的字段信息
* @access public
* @return array
*/
public function getFields($tableName) {
$result = $this->query("SELECT column_name, data_type, column_default, is_nullable
FROM information_schema.tables AS t
JOIN information_schema.columns AS c
ON t.table_catalog = c.table_catalog
AND t.table_schema = c.table_schema
AND t.table_name = c.table_name
WHERE t.table_name = '$tableName'");
$info = array();
if($result) {
foreach ($result as $key => $val) {
$info[$val['column_name']] = array(
'name' => $val['column_name'],
'type' => $val['data_type'],
'notnull' => (bool) ($val['is_nullable'] === ''), // not null is empty, null is yes
'default' => $val['column_default'],
'primary' => false,
'autoinc' => false,
);
}
}
return $info;
}
/**
* 取得数据表的字段信息
* @access public
* @return array
*/
public function getTables($dbName='') {
$result = $this->query("SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
");
$info = array();
foreach ($result as $key => $val) {
$info[$key] = current($val);
}
return $info;
}
/**
* order分析
* @access protected
* @param mixed $order
* @return string
*/
protected function parseOrder($order) {
return !empty($order)? ' ORDER BY '.$order:' ORDER BY rand()';
}
/**
* limit
* @access public
* @return string
*/
public function parseLimit($limit) {
if(empty($limit)) return '';
$limit = explode(',',$limit);
if(count($limit)>1)
$limitStr = '(T1.ROW_NUMBER BETWEEN '.$limit[0].' + 1 AND '.$limit[0].' + '.$limit[1].')';
else
$limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND '.$limit[0].")";
return 'WHERE '.$limitStr;
}
/**
* 更新记录
* @access public
* @param mixed $data 数据
* @param array $options 表达式
* @return false | integer
*/
public function update($data,$options) {
$this->model = $options['model'];
$sql = 'UPDATE '
.$this->parseTable($options['table'])
.$this->parseSet($data)
.$this->parseWhere(!empty($options['where'])?$options['where']:'')
.$this->parseLock(isset($options['lock'])?$options['lock']:false)
.$this->parseComment(!empty($options['comment'])?$options['comment']:'');
return $this->execute($sql);
}
/**
* 删除记录
* @access public
* @param array $options 表达式
* @return false | integer
*/
public function delete($options=array()) {
$this->model = $options['model'];
$sql = 'DELETE FROM '
.$this->parseTable($options['table'])
.$this->parseWhere(!empty($options['where'])?$options['where']:'')
.$this->parseLock(isset($options['lock'])?$options['lock']:false)
.$this->parseComment(!empty($options['comment'])?$options['comment']:'');
return $this->execute($sql);
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if ($this->_linkID){
mssql_close($this->_linkID);
}
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error() {
$this->error = mssql_get_last_message();
if('' != $this->queryStr){
$this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
}
trace($this->error,'','ERR');
return $this->error;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Oracle数据库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author ZhangXuehun <zhangxuehun@sohu.com>
*/
class DbOracle extends Db{
private $mode = OCI_COMMIT_ON_SUCCESS;
private $table = '';
protected $selectSql = 'SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%';
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config=''){
putenv("NLS_LANG=AMERICAN_AMERICA.UTF8");
if ( !extension_loaded('oci8') ) {
throw_exception(L('_NOT_SUPPERT_').'oracle');
}
if(!empty($config)) {
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
$conn = $pconnect ? 'oci_pconnect':'oci_new_connect';
$this->linkID[$linkNum] = $conn($config['username'], $config['password'],$config['database']);//modify by wyfeng at 2008.12.19
if (!$this->linkID[$linkNum]){
$this->error(false);
}
// 标记连接成功
$this->connected = true;
//注销数据库安全信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
oci_free_statement($this->queryID);
$this->queryID = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @return mixed
*/
public function query($str) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//更改事务模式
$this->mode = OCI_COMMIT_ON_SUCCESS;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$this->queryID = oci_parse($this->_linkID,$str);
$this->debug();
if (false === oci_execute($this->queryID, $this->mode)) {
$this->error();
return false;
} else {
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @return integer
*/
public function execute($str) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
// 判断新增操作
$flag = false;
if(preg_match("/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i", $this->queryStr, $match)) {
$this->table = C("DB_SEQUENCE_PREFIX") .str_ireplace(C("DB_PREFIX"), "", $match[2]);
$flag = (boolean)$this->query("SELECT * FROM user_sequences WHERE sequence_name='" . strtoupper($this->table) . "'");
}//modify by wyfeng at 2009.08.28
//更改事务模式
$this->mode = OCI_COMMIT_ON_SUCCESS;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$stmt = oci_parse($this->_linkID,$str);
$this->debug();
if (false === oci_execute($stmt)) {
$this->error();
return false;
} else {
$this->numRows = oci_num_rows($stmt);
$this->lastInsID = $flag?$this->insertLastId():0;//modify by wyfeng at 2009.08.28
return $this->numRows;
}
}
/**
* 启动事务
* @access public
* @return void
*/
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
$this->mode = OCI_DEFAULT;
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit(){
if ($this->transTimes > 0) {
$result = oci_commit($this->_linkID);
if(!$result){
$this->error();
return false;
}
$this->transTimes = 0;
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback(){
if ($this->transTimes > 0) {
$result = oci_rollback($this->_linkID);
if(!$result){
$this->error();
return false;
}
$this->transTimes = 0;
}
return true;
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = array();
$this->numRows = oci_fetch_all($this->queryID, $result, 0, -1, OCI_FETCHSTATEMENT_BY_ROW);
//add by wyfeng at 2008-12-23 强制将字段名转换为小写,以配合Model类函数如count等
if(C("DB_CASE_LOWER")) {
foreach($result as $k=>$v) {
$result[$k] = array_change_key_case($result[$k], CASE_LOWER);
}
}
return $result;
}
/**
* 取得数据表的字段信息
* @access public
*/
public function getFields($tableName) {
$result = $this->query("select a.column_name,data_type,decode(nullable,'Y',0,1) notnull,data_default,decode(a.column_name,b.column_name,1,0) pk "
."from user_tab_columns a,(select column_name from user_constraints c,user_cons_columns col "
."where c.constraint_name=col.constraint_name and c.constraint_type='P'and c.table_name='".strtoupper($tableName)
."') b where table_name='".strtoupper($tableName)."' and a.column_name=b.column_name(+)");
$info = array();
if($result) {
foreach ($result as $key => $val) {
$info[strtolower($val['column_name'])] = array(
'name' => strtolower($val['column_name']),
'type' => strtolower($val['data_type']),
'notnull' => $val['notnull'],
'default' => $val['data_default'],
'primary' => $val['pk'],
'autoinc' => $val['pk'],
);
}
}
return $info;
}
/**
* 取得数据库的表信息(暂时实现取得用户表信息)
* @access public
*/
public function getTables($dbName='') {
$result = $this->query("select table_name from user_tables");
$info = array();
foreach ($result as $key => $val) {
$info[$key] = current($val);
}
return $info;
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if($this->_linkID){
oci_close($this->_linkID);
}
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error($result = true) {
if($result){
$error = oci_error($this->queryID);
}elseif(!$this->_linkID){
$error = oci_error();
}else{
$error = oci_error($this->_linkID);
}
if('' != $this->queryStr){
$error['message'] .= "\n [ SQL语句 ] : ".$this->queryStr;
}
$result? trace($error['message'],'','ERR'):throw_exception($error['message'],'',$error['code']);
$this->error = $error['message'];
return $this->error;
}
/**
* SQL指令安全过滤
* @access public
* @param string $str SQL指令
* @return string
*/
public function escapeString($str) {
return str_ireplace("'", "''", $str);
}
/**
* 获取最后插入id ,仅适用于采用序列+触发器结合生成ID的方式
* 在config.php中指定
'DB_TRIGGER_PREFIX' => 'tr_',
'DB_SEQUENCE_PREFIX' => 'ts_',
* eg:表 tb_user
相对tb_user的序列为:
-- Create sequence
create sequence TS_USER
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
nocache;
相对tb_user,ts_user的触发器为:
create or replace trigger TR_USER
before insert on "TB_USER"
for each row
begin
select "TS_USER".nextval into :NEW.ID from dual;
end;
* @access public
* @return integer
*/
public function insertLastId() {
if(empty($this->table)) {
return 0;
}
$sequenceName = $this->table;
$vo = $this->query("SELECT {$sequenceName}.currval currval FROM dual");
return $vo?$vo[0]["currval"]:0;
}
/**
* limit
* @access public
* @return string
*/
public function parseLimit($limit) {
$limitStr = '';
if(!empty($limit)) {
$limit = explode(',',$limit);
if(count($limit)>1)
$limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0]+$limit[1]) . ")";
else
$limitStr = "(numrow>0 AND numrow<=".$limit[0].")";
}
return $limitStr?' WHERE '.$limitStr:'';
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* PDO数据库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author liu21st <liu21st@gmail.com>
*/
class DbPdo extends Db{
protected $PDOStatement = null;
private $table = '';
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config=''){
if ( !class_exists('PDO') ) {
throw_exception(L('_NOT_SUPPERT_').':PDO');
}
if(!empty($config)) {
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
if($this->pconnect) {
$config['params'][PDO::ATTR_PERSISTENT] = true;
}
//$config['params'][PDO::ATTR_CASE] = C("DB_CASE_LOWER")?PDO::CASE_LOWER:PDO::CASE_UPPER;
try{
$this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$config['params']);
}catch (PDOException $e) {
throw_exception($e->getMessage());
}
// 因为PDO的连接切换可能导致数据库类型不同,因此重新获取下当前的数据库类型
$this->dbType = $this->_getDsnType($config['dsn']);
if(in_array($this->dbType,array('MSSQL','ORACLE','IBASE','OCI'))) {
// 由于PDO对于以上的数据库支持不够完美,所以屏蔽了 如果仍然希望使用PDO 可以注释下面一行代码
throw_exception('由于目前PDO暂时不能完美支持'.$this->dbType.' 请使用官方的'.$this->dbType.'驱动');
}
$this->linkID[$linkNum]->exec('SET NAMES '.C('DB_CHARSET'));
// 标记连接成功
$this->connected = true;
// 注销数据库连接配置信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
$this->PDOStatement = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @param array $bind 参数绑定
* @return mixed
*/
public function query($str,$bind=array()) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
if(!empty($bind)){
$this->queryStr .= '[ '.print_r($bind,true).' ]';
}
//释放前次的查询结果
if ( !empty($this->PDOStatement) ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$this->PDOStatement = $this->_linkID->prepare($str);
if(false === $this->PDOStatement)
throw_exception($this->error());
$result = $this->PDOStatement->execute($bind);
$this->debug();
if ( false === $result ) {
$this->error();
return false;
} else {
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @param array $bind 参数绑定
* @return integer
*/
public function execute($str,$bind=array()) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
if(!empty($bind)){
$this->queryStr .= '[ '.print_r($bind,true).' ]';
}
$flag = false;
if($this->dbType == 'OCI')
{
if(preg_match("/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i", $this->queryStr, $match)) {
$this->table = C("DB_SEQUENCE_PREFIX").str_ireplace(C("DB_PREFIX"), "", $match[2]);
$flag = (boolean)$this->query("SELECT * FROM user_sequences WHERE sequence_name='" . strtoupper($this->table) . "'");
}
}//modify by wyfeng at 2009.08.28
//释放前次的查询结果
if ( !empty($this->PDOStatement) ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$this->PDOStatement = $this->_linkID->prepare($str);
if(false === $this->PDOStatement) {
throw_exception($this->error());
}
$result = $this->PDOStatement->execute($bind);
$this->debug();
if ( false === $result) {
$this->error();
return false;
} else {
$this->numRows = $this->PDOStatement->rowCount();
if($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) {
$this->lastInsID = $this->getLastInsertId();
}
return $this->numRows;
}
}
/**
* 启动事务
* @access public
* @return void
*/
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
$this->_linkID->beginTransaction();
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit() {
if ($this->transTimes > 0) {
$result = $this->_linkID->commit();
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback() {
if ($this->transTimes > 0) {
$result = $this->_linkID->rollback();
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC);
$this->numRows = count( $result );
return $result;
}
/**
* 取得数据表的字段信息
* @access public
*/
public function getFields($tableName) {
$this->initConnect(true);
if(C('DB_DESCRIBE_TABLE_SQL')) {
// 定义特殊的字段查询SQL
$sql = str_replace('%table%',$tableName,C('DB_DESCRIBE_TABLE_SQL'));
}else{
switch($this->dbType) {
case 'MSSQL':
case 'SQLSRV':
$sql = "SELECT column_name as 'Name', data_type as 'Type', column_default as 'Default', is_nullable as 'Null'
FROM information_schema.tables AS t
JOIN information_schema.columns AS c
ON t.table_catalog = c.table_catalog
AND t.table_schema = c.table_schema
AND t.table_name = c.table_name
WHERE t.table_name = '$tableName'";
break;
case 'SQLITE':
$sql = 'PRAGMA table_info ('.$tableName.') ';
break;
case 'ORACLE':
case 'OCI':
$sql = "SELECT a.column_name \"Name\",data_type \"Type\",decode(nullable,'Y',0,1) notnull,data_default \"Default\",decode(a.column_name,b.column_name,1,0) \"pk\" "
."FROM user_tab_columns a,(SELECT column_name FROM user_constraints c,user_cons_columns col "
."WHERE c.constraint_name=col.constraint_name AND c.constraint_type='P' and c.table_name='".strtoupper($tableName)
."') b where table_name='".strtoupper($tableName)."' and a.column_name=b.column_name(+)";
break;
case 'PGSQL':
$sql = 'select fields_name as "Name",fields_type as "Type",fields_not_null as "Null",fields_key_name as "Key",fields_default as "Default",fields_default as "Extra" from table_msg('.$tableName.');';
break;
case 'IBASE':
break;
case 'MYSQL':
default:
$sql = 'DESCRIBE '.$tableName;//备注: 驱动类不只针对mysql,不能加``
}
}
$result = $this->query($sql);
$info = array();
if($result) {
foreach ($result as $key => $val) {
$val = array_change_key_case($val);
$val['name'] = isset($val['name'])?$val['name']:"";
$val['type'] = isset($val['type'])?$val['type']:"";
$name = isset($val['field'])?$val['field']:$val['name'];
$info[$name] = array(
'name' => $name ,
'type' => $val['type'],
'notnull' => (bool)(((isset($val['null'])) && ($val['null'] === '')) || ((isset($val['notnull'])) && ($val['notnull'] === ''))), // not null is empty, null is yes
'default' => isset($val['default'])? $val['default'] :(isset($val['dflt_value'])?$val['dflt_value']:""),
'primary' => isset($val['key'])?strtolower($val['key']) == 'pri':(isset($val['pk'])?$val['pk']:false),
'autoinc' => isset($val['extra'])?strtolower($val['extra']) == 'auto_increment':(isset($val['key'])?$val['key']:false),
);
}
}
return $info;
}
/**
* 取得数据库的表信息
* @access public
*/
public function getTables($dbName='') {
if(C('DB_FETCH_TABLES_SQL')) {
// 定义特殊的表查询SQL
$sql = str_replace('%db%',$dbName,C('DB_FETCH_TABLES_SQL'));
}else{
switch($this->dbType) {
case 'ORACLE':
case 'OCI':
$sql = 'SELECT table_name FROM user_tables';
break;
case 'MSSQL':
case 'SQLSRV':
$sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'";
break;
case 'PGSQL':
$sql = "select tablename as Tables_in_test from pg_tables where schemaname ='public'";
break;
case 'IBASE':
// 暂时不支持
throw_exception(L('_NOT_SUPPORT_DB_').':IBASE');
break;
case 'SQLITE':
$sql = "SELECT name FROM sqlite_master WHERE type='table' "
. "UNION ALL SELECT name FROM sqlite_temp_master "
. "WHERE type='table' ORDER BY name";
break;
case 'MYSQL':
default:
if(!empty($dbName)) {
$sql = 'SHOW TABLES FROM '.$dbName;
}else{
$sql = 'SHOW TABLES ';
}
}
}
$result = $this->query($sql);
$info = array();
foreach ($result as $key => $val) {
$info[$key] = current($val);
}
return $info;
}
/**
* limit分析
* @access protected
* @param mixed $lmit
* @return string
*/
protected function parseLimit($limit) {
$limitStr = '';
if(!empty($limit)) {
switch($this->dbType){
case 'PGSQL':
case 'SQLITE':
$limit = explode(',',$limit);
if(count($limit)>1) {
$limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' ';
}else{
$limitStr .= ' LIMIT '.$limit[0].' ';
}
break;
case 'MSSQL':
case 'SQLSRV':
break;
case 'IBASE':
// 暂时不支持
break;
case 'ORACLE':
case 'OCI':
break;
case 'MYSQL':
default:
$limitStr .= ' LIMIT '.$limit.' ';
}
}
return $limitStr;
}
/**
* 字段和表名处理
* @access protected
* @param string $key
* @return string
*/
protected function parseKey(&$key) {
if($this->dbType=='MYSQL'){
$key = trim($key);
if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) {
$key = '`'.$key.'`';
}
return $key;
}else{
return parent::parseKey($key);
}
}
/**
* 关闭数据库
* @access public
*/
public function close() {
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error() {
if($this->PDOStatement) {
$error = $this->PDOStatement->errorInfo();
$this->error = $error[1].':'.$error[2];
}else{
$this->error = '';
}
if('' != $this->queryStr){
$this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
}
trace($this->error,'','ERR');
return $this->error;
}
/**
* SQL指令安全过滤
* @access public
* @param string $str SQL指令
* @return string
*/
public function escapeString($str) {
switch($this->dbType) {
case 'PGSQL':
case 'MSSQL':
case 'SQLSRV':
case 'MYSQL':
return addslashes($str);
case 'IBASE':
case 'SQLITE':
case 'ORACLE':
case 'OCI':
return str_ireplace("'", "''", $str);
}
}
/**
* value分析
* @access protected
* @param mixed $value
* @return string
*/
protected function parseValue($value) {
if(is_string($value)) {
$value = strpos($value,':') === 0 ? $this->escapeString($value) : '\''.$this->escapeString($value).'\'';
}elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){
$value = $this->escapeString($value[1]);
}elseif(is_array($value)) {
$value = array_map(array($this, 'parseValue'),$value);
}elseif(is_bool($value)){
$value = $value ? '1' : '0';
}elseif(is_null($value)){
$value = 'null';
}
return $value;
}
/**
* 获取最后插入id
* @access public
* @return integer
*/
public function getLastInsertId() {
switch($this->dbType) {
case 'PGSQL':
case 'SQLITE':
case 'MSSQL':
case 'SQLSRV':
case 'IBASE':
case 'MYSQL':
return $this->_linkID->lastInsertId();
case 'ORACLE':
case 'OCI':
$sequenceName = $this->table;
$vo = $this->query("SELECT {$sequenceName}.currval currval FROM dual");
return $vo?$vo[0]["currval"]:0;
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Pgsql数据库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author liu21st <liu21st@gmail.com>
*/
class DbPgsql extends Db{
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config='') {
if ( !extension_loaded('pgsql') ) {
throw_exception(L('_NOT_SUPPERT_').':pgsql');
}
if(!empty($config)) {
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
$conn = $pconnect ? 'pg_pconnect':'pg_connect';
$this->linkID[$linkNum] = $conn('host='.$config['hostname'].' port='.$config['hostport'].' dbname='.$config['database'].' user='.$config['username'].' password='.$config['password']);
if (0 !== pg_connection_status($this->linkID[$linkNum])){
throw_exception($this->error(false));
}
//设置编码
pg_set_client_encoding($this->linkID[$linkNum], C('DB_CHARSET'));
//$pgInfo = pg_version($this->linkID[$linkNum]);
//$dbVersion = $pgInfo['server'];
// 标记连接成功
$this->connected = true;
//注销数据库安全信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
pg_free_result($this->queryID);
$this->queryID = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @return mixed
*/
public function query($str) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$this->queryID = pg_query($this->_linkID,$str);
$this->debug();
if ( false === $this->queryID ) {
$this->error();
return false;
} else {
$this->numRows = pg_num_rows($this->queryID);
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @return integer
*/
public function execute($str) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$result = pg_query($this->_linkID,$str);
$this->debug();
if ( false === $result ) {
$this->error();
return false;
} else {
$this->numRows = pg_affected_rows($result);
$this->lastInsID = $this->last_insert_id();
return $this->numRows;
}
}
/**
* 用于获取最后插入的ID
* @access public
* @return integer
*/
public function last_insert_id() {
$query = "SELECT LASTVAL() AS insert_id";
$result = pg_query($this->_linkID,$query);
list($last_insert_id) = pg_fetch_array($result,null,PGSQL_ASSOC);
pg_free_result($result);
return $last_insert_id;
}
/**
* 启动事务
* @access public
* @return void
*/
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
pg_exec($this->_linkID,'begin;');
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit() {
if ($this->transTimes > 0) {
$result = pg_exec($this->_linkID,'end;');
if(!$result){
$this->error();
return false;
}
$this->transTimes = 0;
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback() {
if ($this->transTimes > 0) {
$result = pg_exec($this->_linkID,'abort;');
if(!$result){
$this->error();
return false;
}
$this->transTimes = 0;
}
return true;
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = pg_fetch_all($this->queryID);
pg_result_seek($this->queryID,0);
return $result;
}
/**
* 取得数据表的字段信息
* @access public
*/
public function getFields($tableName) {
$result = $this->query("select a.attname as \"Field\",
t.typname as \"Type\",
a.attnotnull as \"Null\",
i.indisprimary as \"Key\",
d.adsrc as \"Default\"
from pg_class c
inner join pg_attribute a on a.attrelid = c.oid
inner join pg_type t on a.atttypid = t.oid
left join pg_attrdef d on a.attrelid=d.adrelid and d.adnum=a.attnum
left join pg_index i on a.attnum=ANY(i.indkey) and c.oid = i.indrelid
where (c.relname='{$tableName}' or c.relname = lower('{$tableName}')) AND a.attnum > 0
order by a.attnum asc;");
$info = array();
if($result) {
foreach ($result as $key => $val) {
$info[$val['Field']] = array(
'name' => $val['Field'],
'type' => $val['Type'],
'notnull' => (bool) ($val['Null'] == 't'?1:0), // 't' is 'not null'
'default' => $val['Default'],
'primary' => (strtolower($val['Key']) == 't'),
'autoinc' => (strtolower($val['Default']) == "nextval('{$tableName}_id_seq'::regclass)"),
);
}
}
return $info;
}
/**
* 取得数据库的表信息
* @access public
*/
public function getTables($dbName='') {
$result = $this->query("select tablename as Tables_in_test from pg_tables where schemaname ='public'");
$info = array();
foreach ($result as $key => $val) {
$info[$key] = current($val);
}
return $info;
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if($this->_linkID){
pg_close($this->_linkID);
}
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error($result = true) {
$this->error = $result?pg_result_error($this->queryID): pg_last_error($this->_linkID);
if('' != $this->queryStr){
$this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
}
trace($this->error,'','ERR');
return $this->error;
}
/**
* SQL指令安全过滤
* @access public
* @param string $str SQL指令
* @return string
*/
public function escapeString($str) {
return pg_escape_string($str);
}
/**
* limit
* @access public
* @return string
*/
public function parseLimit($limit) {
$limitStr = '';
if(!empty($limit)) {
$limit = explode(',',$limit);
if(count($limit)>1) {
$limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' ';
}else{
$limitStr .= ' LIMIT '.$limit[0].' ';
}
}
return $limitStr;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Sqlite数据库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author liu21st <liu21st@gmail.com>
*/
class DbSqlite extends Db {
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config='') {
if ( !extension_loaded('sqlite') ) {
throw_exception(L('_NOT_SUPPERT_').':sqlite');
}
if(!empty($config)) {
if(!isset($config['mode'])) {
$config['mode'] = 0666;
}
$this->config = $config;
if(empty($this->config['params'])) {
$this->config['params'] = array();
}
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
$conn = $pconnect ? 'sqlite_popen':'sqlite_open';
$this->linkID[$linkNum] = $conn($config['database'],$config['mode']);
if ( !$this->linkID[$linkNum]) {
throw_exception(sqlite_error_string());
}
// 标记连接成功
$this->connected = true;
//注销数据库安全信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
$this->queryID = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @return mixed
*/
public function query($str) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$this->queryID = sqlite_query($this->_linkID,$str);
$this->debug();
if ( false === $this->queryID ) {
$this->error();
return false;
} else {
$this->numRows = sqlite_num_rows($this->queryID);
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @return integer
*/
public function execute($str) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$result = sqlite_exec($this->_linkID,$str);
$this->debug();
if ( false === $result ) {
$this->error();
return false;
} else {
$this->numRows = sqlite_changes($this->_linkID);
$this->lastInsID = sqlite_last_insert_rowid($this->_linkID);
return $this->numRows;
}
}
/**
* 启动事务
* @access public
* @return void
*/
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
sqlite_query($this->_linkID,'BEGIN TRANSACTION');
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit() {
if ($this->transTimes > 0) {
$result = sqlite_query($this->_linkID,'COMMIT TRANSACTION');
if(!$result){
$this->error();
return false;
}
$this->transTimes = 0;
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback() {
if ($this->transTimes > 0) {
$result = sqlite_query($this->_linkID,'ROLLBACK TRANSACTION');
if(!$result){
$this->error();
return false;
}
$this->transTimes = 0;
}
return true;
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = array();
if($this->numRows >0) {
for($i=0;$i<$this->numRows ;$i++ ){
// 返回数组集
$result[$i] = sqlite_fetch_array($this->queryID,SQLITE_ASSOC);
}
sqlite_seek($this->queryID,0);
}
return $result;
}
/**
* 取得数据表的字段信息
* @access public
* @return array
*/
public function getFields($tableName) {
$result = $this->query('PRAGMA table_info( '.$tableName.' )');
$info = array();
if($result){
foreach ($result as $key => $val) {
$info[$val['Field']] = array(
'name' => $val['Field'],
'type' => $val['Type'],
'notnull' => (bool) ($val['Null'] === ''), // not null is empty, null is yes
'default' => $val['Default'],
'primary' => (strtolower($val['Key']) == 'pri'),
'autoinc' => (strtolower($val['Extra']) == 'auto_increment'),
);
}
}
return $info;
}
/**
* 取得数据库的表信息
* @access public
* @return array
*/
public function getTables($dbName='') {
$result = $this->query("SELECT name FROM sqlite_master WHERE type='table' "
. "UNION ALL SELECT name FROM sqlite_temp_master "
. "WHERE type='table' ORDER BY name");
$info = array();
foreach ($result as $key => $val) {
$info[$key] = current($val);
}
return $info;
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if ($this->_linkID){
sqlite_close($this->_linkID);
}
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error() {
$code = sqlite_last_error($this->_linkID);
$this->error = $code.':'.sqlite_error_string($code);
if('' != $this->queryStr){
$this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
}
trace($this->error,'','ERR');
return $this->error;
}
/**
* SQL指令安全过滤
* @access public
* @param string $str SQL指令
* @return string
*/
public function escapeString($str) {
return sqlite_escape_string($str);
}
/**
* limit
* @access public
* @return string
*/
public function parseLimit($limit) {
$limitStr = '';
if(!empty($limit)) {
$limit = explode(',',$limit);
if(count($limit)>1) {
$limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' ';
}else{
$limitStr .= ' LIMIT '.$limit[0].' ';
}
}
return $limitStr;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Sqlsrv数据库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Db
* @author liu21st <liu21st@gmail.com>
*/
class DbSqlsrv extends Db{
protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%';
/**
* 架构函数 读取数据库配置信息
* @access public
* @param array $config 数据库配置数组
*/
public function __construct($config='') {
if ( !function_exists('sqlsrv_connect') ) {
throw_exception(L('_NOT_SUPPERT_').':sqlsrv');
}
if(!empty($config)) {
$this->config = $config;
}
}
/**
* 连接数据库方法
* @access public
*/
public function connect($config='',$linkNum=0) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
$host = $config['hostname'].($config['hostport']?",{$config['hostport']}":'');
$connectInfo = array('Database'=>$config['database'],'UID'=>$config['username'],'PWD'=>$config['password'],'CharacterSet' => C('DEFAULT_CHARSET'));
$this->linkID[$linkNum] = sqlsrv_connect( $host, $connectInfo);
if ( !$this->linkID[$linkNum] ) $this->error(false);
// 标记连接成功
$this->connected = true;
//注销数据库安全信息
if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
}
return $this->linkID[$linkNum];
}
/**
* 释放查询结果
* @access public
*/
public function free() {
sqlsrv_free_stmt($this->queryID);
$this->queryID = null;
}
/**
* 执行查询 返回数据集
* @access public
* @param string $str sql指令
* @param array $bind 参数绑定
* @return mixed
*/
public function query($str,$bind=array()) {
$this->initConnect(false);
if ( !$this->_linkID ) return false;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_query',1);
// 记录开始执行时间
G('queryStartTime');
$str = str_replace(array_keys($bind),'?',$str);
$bind = array_values($bind);
$this->queryStr = $str;
$this->queryID = sqlsrv_query($this->_linkID,$str,$bind, array( "Scrollable" => SQLSRV_CURSOR_KEYSET));
$this->debug();
if ( false === $this->queryID ) {
$this->error();
return false;
} else {
$this->numRows = sqlsrv_num_rows($this->queryID);
return $this->getAll();
}
}
/**
* 执行语句
* @access public
* @param string $str sql指令
* @param array $bind 参数绑定
* @return integer
*/
public function execute($str,$bind=array()) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//释放前次的查询结果
if ( $this->queryID ) $this->free();
N('db_write',1);
// 记录开始执行时间
G('queryStartTime');
$str = str_replace(array_keys($bind),'?',$str);
$bind = array_values($bind);
$this->queryStr = $str;
$this->queryID= sqlsrv_query($this->_linkID,$str,$bind);
$this->debug();
if ( false === $this->queryID ) {
$this->error();
return false;
} else {
$this->numRows = sqlsrv_rows_affected($this->queryID);
$this->lastInsID = $this->mssql_insert_id();
return $this->numRows;
}
}
/**
* 用于获取最后插入的ID
* @access public
* @return integer
*/
public function mssql_insert_id() {
$query = "SELECT @@IDENTITY as last_insert_id";
$result = sqlsrv_query($this->_linkID,$query);
list($last_insert_id) = sqlsrv_fetch_array($result);
sqlsrv_free_stmt($result);
return $last_insert_id;
}
/**
* 启动事务
* @access public
* @return void
*/
public function startTrans() {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
//数据rollback 支持
if ($this->transTimes == 0) {
sqlsrv_begin_transaction($this->_linkID);
}
$this->transTimes++;
return ;
}
/**
* 用于非自动提交状态下面的查询提交
* @access public
* @return boolen
*/
public function commit() {
if ($this->transTimes > 0) {
$result = sqlsrv_commit($this->_linkID);
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 事务回滚
* @access public
* @return boolen
*/
public function rollback() {
if ($this->transTimes > 0) {
$result = sqlsrv_rollback($this->_linkID);
$this->transTimes = 0;
if(!$result){
$this->error();
return false;
}
}
return true;
}
/**
* 获得所有的查询数据
* @access private
* @return array
*/
private function getAll() {
//返回数据集
$result = array();
if($this->numRows >0) {
while($row = sqlsrv_fetch_array($this->queryID,SQLSRV_FETCH_ASSOC))
$result[] = $row;
}
return $result;
}
/**
* 取得数据表的字段信息
* @access public
* @return array
*/
public function getFields($tableName) {
$result = $this->query("
SELECT column_name,data_type,column_default,is_nullable
FROM information_schema.tables AS t
JOIN information_schema.columns AS c
ON t.table_catalog = c.table_catalog
AND t.table_schema = c.table_schema
AND t.table_name = c.table_name
WHERE t.table_name = '{$tableName}'");
$pk = $this->query("SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='{$tableName}'");
$info = array();
if($result) {
foreach ($result as $key => $val) {
$info[$val['column_name']] = array(
'name' => $val['column_name'],
'type' => $val['data_type'],
'notnull' => (bool) ($val['is_nullable'] === ''), // not null is empty, null is yes
'default' => $val['column_default'],
'primary' => $val['column_name'] == $pk[0]['COLUMN_NAME'],
'autoinc' => false,
);
}
}
return $info;
}
/**
* 取得数据表的字段信息
* @access public
* @return array
*/
public function getTables($dbName='') {
$result = $this->query("SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
");
$info = array();
foreach ($result as $key => $val) {
$info[$key] = current($val);
}
return $info;
}
/**
* order分析
* @access protected
* @param mixed $order
* @return string
*/
protected function parseOrder($order) {
return !empty($order)? ' ORDER BY '.$order:' ORDER BY rand()';
}
/**
* 字段名分析
* @access protected
* @param string $key
* @return string
*/
protected function parseKey(&$key) {
$key = trim($key);
if(!preg_match('/[,\'\"\*\(\)\[.\s]/',$key)) {
$key = '['.$key.']';
}
return $key;
}
/**
* limit
* @access public
* @param mixed $limit
* @return string
*/
public function parseLimit($limit) {
if(empty($limit)) return '';
$limit = explode(',',$limit);
if(count($limit)>1)
$limitStr = '(T1.ROW_NUMBER BETWEEN '.$limit[0].' + 1 AND '.$limit[0].' + '.$limit[1].')';
else
$limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND '.$limit[0].")";
return 'WHERE '.$limitStr;
}
/**
* 更新记录
* @access public
* @param mixed $data 数据
* @param array $options 表达式
* @return false | integer
*/
public function update($data,$options) {
$this->model = $options['model'];
$sql = 'UPDATE '
.$this->parseTable($options['table'])
.$this->parseSet($data)
.$this->parseWhere(!empty($options['where'])?$options['where']:'')
.$this->parseLock(isset($options['lock'])?$options['lock']:false)
.$this->parseComment(!empty($options['comment'])?$options['comment']:'');
return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:array()));
}
/**
* 删除记录
* @access public
* @param array $options 表达式
* @return false | integer
*/
public function delete($options=array()) {
$this->model = $options['model'];
$sql = 'DELETE FROM '
.$this->parseTable($options['table'])
.$this->parseWhere(!empty($options['where'])?$options['where']:'')
.$this->parseLock(isset($options['lock'])?$options['lock']:false)
.$this->parseComment(!empty($options['comment'])?$options['comment']:'');
return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:array()));
}
/**
* 关闭数据库
* @access public
*/
public function close() {
if ($this->_linkID){
sqlsrv_close($this->_linkID);
}
$this->_linkID = null;
}
/**
* 数据库错误信息
* 并显示当前的SQL语句
* @access public
* @return string
*/
public function error($result = true) {
$errors = sqlsrv_errors();
$this->error = '';
foreach( $errors as $error ) {
$this->error .= $error['code'].':'.$error['message'];
}
if('' != $this->queryStr){
$this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
}
$result? trace($this->error,'','ERR'):throw_exception($this->error);
return $this->error;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* 数据库方式Session驱动
* CREATE TABLE think_session (
* session_id varchar(255) NOT NULL,
* session_expire int(11) NOT NULL,
* session_data blob,
* UNIQUE KEY `session_id` (`session_id`)
* );
* @category Extend
* @package Extend
* @subpackage Driver.Session
* @author liu21st <liu21st@gmail.com>
*/
class SessionDb {
/**
* Session有效时间
*/
protected $lifeTime = '';
/**
* session保存的数据库名
*/
protected $sessionTable = '';
/**
* 数据库句柄
*/
protected $hander = array();
/**
* 打开Session
* @access public
* @param string $savePath
* @param mixed $sessName
*/
public function open($savePath, $sessName) {
$this->lifeTime = C('SESSION_EXPIRE')?C('SESSION_EXPIRE'):ini_get('session.gc_maxlifetime');
$this->sessionTable = C('SESSION_TABLE')?C('SESSION_TABLE'):C("DB_PREFIX")."session";
//分布式数据库
$host = explode(',',C('DB_HOST'));
$port = explode(',',C('DB_PORT'));
$name = explode(',',C('DB_NAME'));
$user = explode(',',C('DB_USER'));
$pwd = explode(',',C('DB_PWD'));
if(1 == C('DB_DEPLOY_TYPE')){
//读写分离
if(C('DB_RW_SEPARATE')){
$w = floor(mt_rand(0,C('DB_MASTER_NUM')-1));
if(is_numeric(C('DB_SLAVE_NO'))){//指定服务器读
$r = C('DB_SLAVE_NO');
}else{
$r = floor(mt_rand(C('DB_MASTER_NUM'),count($host)-1));
}
//主数据库链接
$hander = mysql_connect(
$host[$w].(isset($port[$w])?':'.$port[$w]:':'.$port[0]),
isset($user[$w])?$user[$w]:$user[0],
isset($pwd[$w])?$pwd[$w]:$pwd[0]
);
$dbSel = mysql_select_db(
isset($name[$w])?$name[$w]:$name[0]
,$hander);
if(!$hander || !$dbSel)
return false;
$this->hander[0] = $hander;
//从数据库链接
$hander = mysql_connect(
$host[$r].(isset($port[$r])?':'.$port[$r]:':'.$port[0]),
isset($user[$r])?$user[$r]:$user[0],
isset($pwd[$r])?$pwd[$r]:$pwd[0]
);
$dbSel = mysql_select_db(
isset($name[$r])?$name[$r]:$name[0]
,$hander);
if(!$hander || !$dbSel)
return false;
$this->hander[1] = $hander;
return true;
}
}
//从数据库链接
$r = floor(mt_rand(0,count($host)-1));
$hander = mysql_connect(
$host[$r].(isset($port[$r])?':'.$port[$r]:':'.$port[0]),
isset($user[$r])?$user[$r]:$user[0],
isset($pwd[$r])?$pwd[$r]:$pwd[0]
);
$dbSel = mysql_select_db(
isset($name[$r])?$name[$r]:$name[0]
,$hander);
if(!$hander || !$dbSel)
return false;
$this->hander = $hander;
return true;
}
/**
* 关闭Session
* @access public
*/
public function close() {
if(is_array($this->hander)){
$this->gc($this->lifeTime);
return (mysql_close($this->hander[0]) && mysql_close($this->hander[1]));
}
$this->gc($this->lifeTime);
return mysql_close($this->hander);
}
/**
* 读取Session
* @access public
* @param string $sessID
*/
public function read($sessID) {
$hander = is_array($this->hander)?$this->hander[1]:$this->hander;
$res = mysql_query("SELECT session_data AS data FROM ".$this->sessionTable." WHERE session_id = '$sessID' AND session_expire >".time(),$hander);
if($res) {
$row = mysql_fetch_assoc($res);
return $row['data'];
}
return "";
}
/**
* 写入Session
* @access public
* @param string $sessID
* @param String $sessData
*/
public function write($sessID,$sessData) {
$hander = is_array($this->hander)?$this->hander[0]:$this->hander;
$expire = time() + $this->lifeTime;
mysql_query("REPLACE INTO ".$this->sessionTable." ( session_id, session_expire, session_data) VALUES( '$sessID', '$expire', '$sessData')",$hander);
if(mysql_affected_rows($hander))
return true;
return false;
}
/**
* 删除Session
* @access public
* @param string $sessID
*/
public function destroy($sessID) {
$hander = is_array($this->hander)?$this->hander[0]:$this->hander;
mysql_query("DELETE FROM ".$this->sessionTable." WHERE session_id = '$sessID'",$hander);
if(mysql_affected_rows($hander))
return true;
return false;
}
/**
* Session 垃圾回收
* @access public
* @param string $sessMaxLifeTime
*/
public function gc($sessMaxLifeTime) {
$hander = is_array($this->hander)?$this->hander[0]:$this->hander;
mysql_query("DELETE FROM ".$this->sessionTable." WHERE session_expire < ".time(),$hander);
return mysql_affected_rows($hander);
}
/**
* 打开Session
* @access public
*/
public function execute() {
session_set_save_handler(array(&$this,"open"),
array(&$this,"close"),
array(&$this,"read"),
array(&$this,"write"),
array(&$this,"destroy"),
array(&$this,"gc"));
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Html标签库驱动
* @category Extend
* @package Extend
* @subpackage Driver.Taglib
* @author liu21st <liu21st@gmail.com>
*/
class TagLibHtml extends TagLib{
// 标签定义
protected $tags = array(
// 标签定义: attr 属性列表 close 是否闭合(0 或者1 默认1) alias 标签别名 level 嵌套层次
'editor' => array('attr'=>'id,name,style,width,height,type','close'=>1),
'select' => array('attr'=>'name,options,values,output,multiple,id,size,first,change,selected,dblclick','close'=>0),
'grid' => array('attr'=>'id,pk,style,action,actionlist,show,datasource','close'=>0),
'list' => array('attr'=>'id,pk,style,action,actionlist,show,datasource,checkbox','close'=>0),
'imagebtn' => array('attr'=>'id,name,value,type,style,click','close'=>0),
'checkbox' => array('attr'=>'name,checkboxes,checked,separator','close'=>0),
'radio' => array('attr'=>'name,radios,checked,separator','close'=>0)
);
/**
* editor标签解析 插入可视化编辑器
* 格式: <html:editor id="editor" name="remark" type="FCKeditor" style="" >{$vo.remark}</html:editor>
* @access public
* @param string $attr 标签属性
* @return string|void
*/
public function _editor($attr,$content) {
$tag = $this->parseXmlAttr($attr,'editor');
$id = !empty($tag['id'])?$tag['id']: '_editor';
$name = $tag['name'];
$style = !empty($tag['style'])?$tag['style']:'';
$width = !empty($tag['width'])?$tag['width']: '100%';
$height = !empty($tag['height'])?$tag['height'] :'320px';
// $content = $tag['content'];
$type = $tag['type'] ;
switch(strtoupper($type)) {
case 'FCKEDITOR':
$parseStr = '<!-- 编辑器调用开始 --><script type="text/javascript" src="__ROOT__/Public/Js/FCKeditor/fckeditor.js"></script><textarea id="'.$id.'" name="'.$name.'">'.$content.'</textarea><script type="text/javascript"> var oFCKeditor = new FCKeditor( "'.$id.'","'.$width.'","'.$height.'" ) ; oFCKeditor.BasePath = "__ROOT__/Public/Js/FCKeditor/" ; oFCKeditor.ReplaceTextarea() ;function resetEditor(){setContents("'.$id.'",document.getElementById("'.$id.'").value)}; function saveEditor(){document.getElementById("'.$id.'").value = getContents("'.$id.'");} function InsertHTML(html){ var oEditor = FCKeditorAPI.GetInstance("'.$id.'") ;if (oEditor.EditMode == FCK_EDITMODE_WYSIWYG ){oEditor.InsertHtml(html) ;}else alert( "FCK必须处于WYSIWYG模式!" ) ;}</script> <!-- 编辑器调用结束 -->';
break;
case 'FCKMINI':
$parseStr = '<!-- 编辑器调用开始 --><script type="text/javascript" src="__ROOT__/Public/Js/FCKMini/fckeditor.js"></script><textarea id="'.$id.'" name="'.$name.'">'.$content.'</textarea><script type="text/javascript"> var oFCKeditor = new FCKeditor( "'.$id.'","'.$width.'","'.$height.'" ) ; oFCKeditor.BasePath = "__ROOT__/Public/Js/FCKMini/" ; oFCKeditor.ReplaceTextarea() ;function resetEditor(){setContents("'.$id.'",document.getElementById("'.$id.'").value)}; function saveEditor(){document.getElementById("'.$id.'").value = getContents("'.$id.'");} function InsertHTML(html){ var oEditor = FCKeditorAPI.GetInstance("'.$id.'") ;if (oEditor.EditMode == FCK_EDITMODE_WYSIWYG ){oEditor.InsertHtml(html) ;}else alert( "FCK必须处于WYSIWYG模式!" ) ;}</script> <!-- 编辑器调用结束 -->';
break;
case 'EWEBEDITOR':
$parseStr = "<!-- 编辑器调用开始 --><script type='text/javascript' src='__ROOT__/Public/Js/eWebEditor/js/edit.js'></script><input type='hidden' id='{$id}' name='{$name}' value='{$conent}'><iframe src='__ROOT__/Public/Js/eWebEditor/ewebeditor.htm?id={$name}' frameborder=0 scrolling=no width='{$width}' height='{$height}'></iframe><script type='text/javascript'>function saveEditor(){document.getElementById('{$id}').value = getHTML();} </script><!-- 编辑器调用结束 -->";
break;
case 'NETEASE':
$parseStr = '<!-- 编辑器调用开始 --><textarea id="'.$id.'" name="'.$name.'" style="display:none">'.$content.'</textarea><iframe ID="Editor" name="Editor" src="__ROOT__/Public/Js/HtmlEditor/index.html?ID='.$name.'" frameBorder="0" marginHeight="0" marginWidth="0" scrolling="No" style="height:'.$height.';width:'.$width.'"></iframe><!-- 编辑器调用结束 -->';
break;
case 'UBB':
$parseStr = '<script type="text/javascript" src="__ROOT__/Public/Js/UbbEditor.js"></script><div style="padding:1px;width:'.$width.';border:1px solid silver;float:left;"><script LANGUAGE="JavaScript"> showTool(); </script></div><div><TEXTAREA id="UBBEditor" name="'.$name.'" style="clear:both;float:none;width:'.$width.';height:'.$height.'" >'.$content.'</TEXTAREA></div><div style="padding:1px;width:'.$width.';border:1px solid silver;float:left;"><script LANGUAGE="JavaScript">showEmot(); </script></div>';
break;
case 'KINDEDITOR':
$parseStr = '<script type="text/javascript" src="__ROOT__/Public/Js/KindEditor/kindeditor.js"></script><script type="text/javascript"> KE.show({ id : \''.$id.'\' ,urlType : "absolute"});</script><textarea id="'.$id.'" style="'.$style.'" name="'.$name.'" >'.$content.'</textarea>';
break;
default :
$parseStr = '<textarea id="'.$id.'" style="'.$style.'" name="'.$name.'" >'.$content.'</textarea>';
}
return $parseStr;
}
/**
* imageBtn标签解析
* 格式: <html:imageBtn type="" value="" />
* @access public
* @param string $attr 标签属性
* @return string|void
*/
public function _imageBtn($attr) {
$tag = $this->parseXmlAttr($attr,'imageBtn');
$name = $tag['name']; //名称
$value = $tag['value']; //文字
$id = isset($tag['id'])?$tag['id']:''; //ID
$style = isset($tag['style'])?$tag['style']:''; //样式名
$click = isset($tag['click'])?$tag['click']:''; //点击
$type = empty($tag['type'])?'button':$tag['type']; //按钮类型
if(!empty($name)) {
$parseStr = '<div class="'.$style.'" ><input type="'.$type.'" id="'.$id.'" name="'.$name.'" value="'.$value.'" onclick="'.$click.'" class="'.$name.' imgButton"></div>';
}else {
$parseStr = '<div class="'.$style.'" ><input type="'.$type.'" id="'.$id.'" name="'.$name.'" value="'.$value.'" onclick="'.$click.'" class="button"></div>';
}
return $parseStr;
}
/**
* imageLink标签解析
* 格式: <html:imageLink type="" value="" />
* @access public
* @param string $attr 标签属性
* @return string|void
*/
public function _imgLink($attr) {
$tag = $this->parseXmlAttr($attr,'imgLink');
$name = $tag['name']; //名称
$alt = $tag['alt']; //文字
$id = $tag['id']; //ID
$style = $tag['style']; //样式名
$click = $tag['click']; //点击
$type = $tag['type']; //点击
if(empty($type)) {
$type = 'button';
}
$parseStr = '<span class="'.$style.'" ><input title="'.$alt.'" type="'.$type.'" id="'.$id.'" name="'.$name.'" onmouseover="this.style.filter=\'alpha(opacity=100)\'" onmouseout="this.style.filter=\'alpha(opacity=80)\'" onclick="'.$click.'" align="absmiddle" class="'.$name.' imgLink"></span>';
return $parseStr;
}
/**
* select标签解析
* 格式: <html:select options="name" selected="value" />
* @access public
* @param string $attr 标签属性
* @return string|void
*/
public function _select($attr) {
$tag = $this->parseXmlAttr($attr,'select');
$name = $tag['name'];
$options = $tag['options'];
$values = $tag['values'];
$output = $tag['output'];
$multiple = $tag['multiple'];
$id = $tag['id'];
$size = $tag['size'];
$first = $tag['first'];
$selected = $tag['selected'];
$style = $tag['style'];
$ondblclick = $tag['dblclick'];
$onchange = $tag['change'];
if(!empty($multiple)) {
$parseStr = '<select id="'.$id.'" name="'.$name.'" ondblclick="'.$ondblclick.'" onchange="'.$onchange.'" multiple="multiple" class="'.$style.'" size="'.$size.'" >';
}else {
$parseStr = '<select id="'.$id.'" name="'.$name.'" onchange="'.$onchange.'" ondblclick="'.$ondblclick.'" class="'.$style.'" >';
}
if(!empty($first)) {
$parseStr .= '<option value="" >'.$first.'</option>';
}
if(!empty($options)) {
$parseStr .= '<?php foreach($'.$options.' as $key=>$val) { ?>';
if(!empty($selected)) {
$parseStr .= '<?php if(!empty($'.$selected.') && ($'.$selected.' == $key || in_array($key,$'.$selected.'))) { ?>';
$parseStr .= '<option selected="selected" value="<?php echo $key ?>"><?php echo $val ?></option>';
$parseStr .= '<?php }else { ?><option value="<?php echo $key ?>"><?php echo $val ?></option>';
$parseStr .= '<?php } ?>';
}else {
$parseStr .= '<option value="<?php echo $key ?>"><?php echo $val ?></option>';
}
$parseStr .= '<?php } ?>';
}else if(!empty($values)) {
$parseStr .= '<?php for($i=0;$i<count($'.$values.');$i++) { ?>';
if(!empty($selected)) {
$parseStr .= '<?php if(isset($'.$selected.') && ((is_string($'.$selected.') && $'.$selected.' == $'.$values.'[$i]) || (is_array($'.$selected.') && in_array($'.$values.'[$i],$'.$selected.')))) { ?>';
$parseStr .= '<option selected="selected" value="<?php echo $'.$values.'[$i] ?>"><?php echo $'.$output.'[$i] ?></option>';
$parseStr .= '<?php }else { ?><option value="<?php echo $'.$values.'[$i] ?>"><?php echo $'.$output.'[$i] ?></option>';
$parseStr .= '<?php } ?>';
}else {
$parseStr .= '<option value="<?php echo $'.$values.'[$i] ?>"><?php echo $'.$output.'[$i] ?></option>';
}
$parseStr .= '<?php } ?>';
}
$parseStr .= '</select>';
return $parseStr;
}
/**
* checkbox标签解析
* 格式: <html:checkbox checkboxes="" checked="" />
* @access public
* @param string $attr 标签属性
* @return string|void
*/
public function _checkbox($attr) {
$tag = $this->parseXmlAttr($attr,'checkbox');
$name = $tag['name'];
$checkboxes = $tag['checkboxes'];
$checked = $tag['checked'];
$separator = $tag['separator'];
$checkboxes = $this->tpl->get($checkboxes);
$checked = $this->tpl->get($checked)?$this->tpl->get($checked):$checked;
$parseStr = '';
foreach($checkboxes as $key=>$val) {
if($checked == $key || in_array($key,$checked) ) {
$parseStr .= '<input type="checkbox" checked="checked" name="'.$name.'[]" value="'.$key.'">'.$val.$separator;
}else {
$parseStr .= '<input type="checkbox" name="'.$name.'[]" value="'.$key.'">'.$val.$separator;
}
}
return $parseStr;
}
/**
* radio标签解析
* 格式: <html:radio radios="name" checked="value" />
* @access public
* @param string $attr 标签属性
* @return string|void
*/
public function _radio($attr) {
$tag = $this->parseXmlAttr($attr,'radio');
$name = $tag['name'];
$radios = $tag['radios'];
$checked = $tag['checked'];
$separator = $tag['separator'];
$radios = $this->tpl->get($radios);
$checked = $this->tpl->get($checked)?$this->tpl->get($checked):$checked;
$parseStr = '';
foreach($radios as $key=>$val) {
if($checked == $key ) {
$parseStr .= '<input type="radio" checked="checked" name="'.$name.'[]" value="'.$key.'">'.$val.$separator;
}else {
$parseStr .= '<input type="radio" name="'.$name.'[]" value="'.$key.'">'.$val.$separator;
}
}
return $parseStr;
}
/**
* list标签解析
* 格式: <html:grid datasource="" show="vo" />
* @access public
* @param string $attr 标签属性
* @return string
*/
public function _grid($attr) {
$tag = $this->parseXmlAttr($attr,'grid');
$id = $tag['id']; //表格ID
$datasource = $tag['datasource']; //列表显示的数据源VoList名称
$pk = empty($tag['pk'])?'id':$tag['pk'];//主键名,默认为id
$style = $tag['style']; //样式名
$name = !empty($tag['name'])?$tag['name']:'vo'; //Vo对象名
$action = !empty($tag['action'])?$tag['action']:false; //是否显示功能操作
$key = !empty($tag['key'])?true:false;
if(isset($tag['actionlist'])) {
$actionlist = explode(',',trim($tag['actionlist'])); //指定功能列表
}
if(substr($tag['show'],0,1)=='$') {
$show = $this->tpl->get(substr($tag['show'],1));
}else {
$show = $tag['show'];
}
$show = explode(',',$show); //列表显示字段列表
//计算表格的列数
$colNum = count($show);
if(!empty($action)) $colNum++;
if(!empty($key)) $colNum++;
//显示开始
$parseStr = "<!-- Think 系统列表组件开始 -->\n";
$parseStr .= '<table id="'.$id.'" class="'.$style.'" cellpadding=0 cellspacing=0 >';
$parseStr .= '<tr><td height="5" colspan="'.$colNum.'" class="topTd" ></td></tr>';
$parseStr .= '<tr class="row" >';
//列表需要显示的字段
$fields = array();
foreach($show as $val) {
$fields[] = explode(':',$val);
}
if(!empty($key)) {
$parseStr .= '<th width="12">No</th>';
}
foreach($fields as $field) {//显示指定的字段
$property = explode('|',$field[0]);
$showname = explode('|',$field[1]);
if(isset($showname[1])) {
$parseStr .= '<th width="'.$showname[1].'">';
}else {
$parseStr .= '<th>';
}
$parseStr .= $showname[0].'</th>';
}
if(!empty($action)) {//如果指定显示操作功能列
$parseStr .= '<th >操作</th>';
}
$parseStr .= '</tr>';
$parseStr .= '<volist name="'.$datasource.'" id="'.$name.'" ><tr class="row" >'; //支持鼠标移动单元行颜色变化 具体方法在js中定义
if(!empty($key)) {
$parseStr .= '<td>{$i}</td>';
}
foreach($fields as $field) {
//显示定义的列表字段
$parseStr .= '<td>';
if(!empty($field[2])) {
// 支持列表字段链接功能 具体方法由JS函数实现
$href = explode('|',$field[2]);
if(count($href)>1) {
//指定链接传的字段值
// 支持多个字段传递
$array = explode('^',$href[1]);
if(count($array)>1) {
foreach ($array as $a){
$temp[] = '\'{$'.$name.'.'.$a.'|addslashes}\'';
}
$parseStr .= '<a href="javascript:'.$href[0].'('.implode(',',$temp).')">';
}else{
$parseStr .= '<a href="javascript:'.$href[0].'(\'{$'.$name.'.'.$href[1].'|addslashes}\')">';
}
}else {
//如果没有指定默认传编号值
$parseStr .= '<a href="javascript:'.$field[2].'(\'{$'.$name.'.'.$pk.'|addslashes}\')">';
}
}
if(strpos($field[0],'^')) {
$property = explode('^',$field[0]);
foreach ($property as $p){
$unit = explode('|',$p);
if(count($unit)>1) {
$parseStr .= '{$'.$name.'.'.$unit[0].'|'.$unit[1].'} ';
}else {
$parseStr .= '{$'.$name.'.'.$p.'} ';
}
}
}else{
$property = explode('|',$field[0]);
if(count($property)>1) {
$parseStr .= '{$'.$name.'.'.$property[0].'|'.$property[1].'}';
}else {
$parseStr .= '{$'.$name.'.'.$field[0].'}';
}
}
if(!empty($field[2])) {
$parseStr .= '</a>';
}
$parseStr .= '</td>';
}
if(!empty($action)) {//显示功能操作
if(!empty($actionlist[0])) {//显示指定的功能项
$parseStr .= '<td>';
foreach($actionlist as $val) {
if(strpos($val,':')) {
$a = explode(':',$val);
if(count($a)>2) {
$parseStr .= '<a href="javascript:'.$a[0].'(\'{$'.$name.'.'.$a[2].'}\')">'.$a[1].'</a>&nbsp;';
}else {
$parseStr .= '<a href="javascript:'.$a[0].'(\'{$'.$name.'.'.$pk.'}\')">'.$a[1].'</a>&nbsp;';
}
}else{
$array = explode('|',$val);
if(count($array)>2) {
$parseStr .= ' <a href="javascript:'.$array[1].'(\'{$'.$name.'.'.$array[0].'}\')">'.$array[2].'</a>&nbsp;';
}else{
$parseStr .= ' {$'.$name.'.'.$val.'}&nbsp;';
}
}
}
$parseStr .= '</td>';
}
}
$parseStr .= '</tr></volist><tr><td height="5" colspan="'.$colNum.'" class="bottomTd"></td></tr></table>';
$parseStr .= "\n<!-- Think 系统列表组件结束 -->\n";
return $parseStr;
}
/**
* list标签解析
* 格式: <html:list datasource="" show="" />
* @access public
* @param string $attr 标签属性
* @return string
*/
public function _list($attr) {
$tag = $this->parseXmlAttr($attr,'list');
$id = $tag['id']; //表格ID
$datasource = $tag['datasource']; //列表显示的数据源VoList名称
$pk = empty($tag['pk'])?'id':$tag['pk'];//主键名,默认为id
$style = $tag['style']; //样式名
$name = !empty($tag['name'])?$tag['name']:'vo'; //Vo对象名
$action = $tag['action']=='true'?true:false; //是否显示功能操作
$key = !empty($tag['key'])?true:false;
$sort = $tag['sort']=='false'?false:true;
$checkbox = $tag['checkbox']; //是否显示Checkbox
if(isset($tag['actionlist'])) {
$actionlist = explode(',',trim($tag['actionlist'])); //指定功能列表
}
if(substr($tag['show'],0,1)=='$') {
$show = $this->tpl->get(substr($tag['show'],1));
}else {
$show = $tag['show'];
}
$show = explode(',',$show); //列表显示字段列表
//计算表格的列数
$colNum = count($show);
if(!empty($checkbox)) $colNum++;
if(!empty($action)) $colNum++;
if(!empty($key)) $colNum++;
//显示开始
$parseStr = "<!-- Think 系统列表组件开始 -->\n";
$parseStr .= '<table id="'.$id.'" class="'.$style.'" cellpadding=0 cellspacing=0 >';
$parseStr .= '<tr><td height="5" colspan="'.$colNum.'" class="topTd" ></td></tr>';
$parseStr .= '<tr class="row" >';
//列表需要显示的字段
$fields = array();
foreach($show as $val) {
$fields[] = explode(':',$val);
}
if(!empty($checkbox) && 'true'==strtolower($checkbox)) {//如果指定需要显示checkbox列
$parseStr .='<th width="8"><input type="checkbox" id="check" onclick="CheckAll(\''.$id.'\')"></th>';
}
if(!empty($key)) {
$parseStr .= '<th width="12">No</th>';
}
foreach($fields as $field) {//显示指定的字段
$property = explode('|',$field[0]);
$showname = explode('|',$field[1]);
if(isset($showname[1])) {
$parseStr .= '<th width="'.$showname[1].'">';
}else {
$parseStr .= '<th>';
}
$showname[2] = isset($showname[2])?$showname[2]:$showname[0];
if($sort) {
$parseStr .= '<a href="javascript:sortBy(\''.$property[0].'\',\'{$sort}\',\''.ACTION_NAME.'\')" title="按照'.$showname[2].'{$sortType} ">'.$showname[0].'<eq name="order" value="'.$property[0].'" ><img src="../Public/images/{$sortImg}.gif" width="12" height="17" border="0" align="absmiddle"></eq></a></th>';
}else{
$parseStr .= $showname[0].'</th>';
}
}
if(!empty($action)) {//如果指定显示操作功能列
$parseStr .= '<th >操作</th>';
}
$parseStr .= '</tr>';
$parseStr .= '<volist name="'.$datasource.'" id="'.$name.'" ><tr class="row" '; //支持鼠标移动单元行颜色变化 具体方法在js中定义
if(!empty($checkbox)) {
$parseStr .= 'onmouseover="over(event)" onmouseout="out(event)" onclick="change(event)" ';
}
$parseStr .= '>';
if(!empty($checkbox)) {//如果需要显示checkbox 则在每行开头显示checkbox
$parseStr .= '<td><input type="checkbox" name="key" value="{$'.$name.'.'.$pk.'}"></td>';
}
if(!empty($key)) {
$parseStr .= '<td>{$i}</td>';
}
foreach($fields as $field) {
//显示定义的列表字段
$parseStr .= '<td>';
if(!empty($field[2])) {
// 支持列表字段链接功能 具体方法由JS函数实现
$href = explode('|',$field[2]);
if(count($href)>1) {
//指定链接传的字段值
// 支持多个字段传递
$array = explode('^',$href[1]);
if(count($array)>1) {
foreach ($array as $a){
$temp[] = '\'{$'.$name.'.'.$a.'|addslashes}\'';
}
$parseStr .= '<a href="javascript:'.$href[0].'('.implode(',',$temp).')">';
}else{
$parseStr .= '<a href="javascript:'.$href[0].'(\'{$'.$name.'.'.$href[1].'|addslashes}\')">';
}
}else {
//如果没有指定默认传编号值
$parseStr .= '<a href="javascript:'.$field[2].'(\'{$'.$name.'.'.$pk.'|addslashes}\')">';
}
}
if(strpos($field[0],'^')) {
$property = explode('^',$field[0]);
foreach ($property as $p){
$unit = explode('|',$p);
if(count($unit)>1) {
$parseStr .= '{$'.$name.'.'.$unit[0].'|'.$unit[1].'} ';
}else {
$parseStr .= '{$'.$name.'.'.$p.'} ';
}
}
}else{
$property = explode('|',$field[0]);
if(count($property)>1) {
$parseStr .= '{$'.$name.'.'.$property[0].'|'.$property[1].'}';
}else {
$parseStr .= '{$'.$name.'.'.$field[0].'}';
}
}
if(!empty($field[2])) {
$parseStr .= '</a>';
}
$parseStr .= '</td>';
}
if(!empty($action)) {//显示功能操作
if(!empty($actionlist[0])) {//显示指定的功能项
$parseStr .= '<td>';
foreach($actionlist as $val) {
if(strpos($val,':')) {
$a = explode(':',$val);
if(count($a)>2) {
$parseStr .= '<a href="javascript:'.$a[0].'(\'{$'.$name.'.'.$a[2].'}\')">'.$a[1].'</a>&nbsp;';
}else {
$parseStr .= '<a href="javascript:'.$a[0].'(\'{$'.$name.'.'.$pk.'}\')">'.$a[1].'</a>&nbsp;';
}
}else{
$array = explode('|',$val);
if(count($array)>2) {
$parseStr .= ' <a href="javascript:'.$array[1].'(\'{$'.$name.'.'.$array[0].'}\')">'.$array[2].'</a>&nbsp;';
}else{
$parseStr .= ' {$'.$name.'.'.$val.'}&nbsp;';
}
}
}
$parseStr .= '</td>';
}
}
$parseStr .= '</tr></volist><tr><td height="5" colspan="'.$colNum.'" class="bottomTd"></td></tr></table>';
$parseStr .= "\n<!-- Think 系统列表组件结束 -->\n";
return $parseStr;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* EaseTemplate模板引擎驱动
* @category Extend
* @package Extend
* @subpackage Driver.Template
* @author liu21st <liu21st@gmail.com>
*/
class TemplateEase {
/**
* 渲染模板输出
* @access public
* @param string $templateFile 模板文件名
* @param array $var 模板变量
* @return void
*/
public function fetch($templateFile,$var) {
$templateFile = substr($templateFile,strlen(THEME_PATH),-5);
$CacheDir = substr(CACHE_PATH,0,-1);
$TemplateDir = substr(THEME_PATH,0,-1);
vendor('EaseTemplate.template#ease');
$config = array(
'CacheDir' => $CacheDir,
'TemplateDir' => $TemplateDir,
'TplType' => 'html'
);
if(C('TMPL_ENGINE_CONFIG')) {
$config = array_merge($config,C('TMPL_ENGINE_CONFIG'));
}
$tpl = new EaseTemplate($config);
$tpl->set_var($var);
$tpl->set_file($templateFile);
$tpl->p();
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* TemplateLite模板引擎驱动
* @category Extend
* @package Extend
* @subpackage Driver.Template
* @author liu21st <liu21st@gmail.com>
*/
class TemplateLite {
/**
* 渲染模板输出
* @access public
* @param string $templateFile 模板文件名
* @param array $var 模板变量
* @return void
*/
public function fetch($templateFile,$var) {
vendor("TemplateLite.class#template");
$templateFile = substr($templateFile,strlen(THEME_PATH));
$tpl = new Template_Lite();
$tpl->template_dir = THEME_PATH;
$tpl->compile_dir = CACHE_PATH ;
$tpl->cache_dir = TEMP_PATH ;
if(C('TMPL_ENGINE_CONFIG')) {
$config = C('TMPL_ENGINE_CONFIG');
foreach ($config as $key=>$val){
$tpl->{$key} = $val;
}
}
$tpl->assign($var);
$tpl->display($templateFile);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2013 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614<weibo.com/luofei614>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* MobileTemplate模板引擎驱动
* @category Extend
* @package Extend
* @subpackage Driver.Template
* @author luofei614 <weibo.com/luofei614>
*/
class TemplateMobile {
/**
* 渲染模板输出
* @access public
* @param string $templateFile 模板文件名
* @param array $var 模板变量
* @return void
*/
public function fetch($templateFile,$var) {
$templateFile=substr($templateFile,strlen(THEME_PATH));
$var['_think_template_path']=$templateFile;
exit(json_encode($var));
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Smart模板引擎驱动
* @category Extend
* @package Extend
* @subpackage Driver.Template
* @author liu21st <liu21st@gmail.com>
*/
class TemplateSmart {
/**
* 渲染模板输出
* @access public
* @param string $templateFile 模板文件名
* @param array $var 模板变量
* @return void
*/
public function fetch($templateFile,$var) {
$templateFile = substr($templateFile,strlen(THEME_PATH));
vendor('SmartTemplate.class#smarttemplate');
$tpl = new SmartTemplate($templateFile);
$tpl->caching = C('TMPL_CACHE_ON');
$tpl->template_dir = THEME_PATH;
$tpl->compile_dir = CACHE_PATH ;
$tpl->cache_dir = TEMP_PATH ;
if(C('TMPL_ENGINE_CONFIG')) {
$config = C('TMPL_ENGINE_CONFIG');
foreach ($config as $key=>$val){
$tpl->{$key} = $val;
}
}
$tpl->assign($var);
$tpl->output();
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
defined('THINK_PATH') or exit();
/**
* Smarty模板引擎驱动
* @category Extend
* @package Extend
* @subpackage Driver.Template
* @author liu21st <liu21st@gmail.com>
*/
class TemplateSmarty {
/**
* 渲染模板输出
* @access public
* @param string $templateFile 模板文件名
* @param array $var 模板变量
* @return void
*/
public function fetch($templateFile,$var) {
$templateFile = substr($templateFile,strlen(THEME_PATH));
vendor('Smarty.Smarty#class');
$tpl = new Smarty();
$tpl->caching = C('TMPL_CACHE_ON');
$tpl->template_dir = THEME_PATH;
$tpl->compile_dir = CACHE_PATH ;
$tpl->cache_dir = TEMP_PATH ;
if(C('TMPL_ENGINE_CONFIG')) {
$config = C('TMPL_ENGINE_CONFIG');
foreach ($config as $key=>$val){
$tpl->{$key} = $val;
}
}
$tpl->assign($var);
$tpl->display($templateFile);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Think扩展函数库 需要手动加载后调用或者放入项目函数库
* @category Extend
* @package Extend
* @subpackage Function
* @author liu21st <liu21st@gmail.com>
*/
/**
* 字符串截取,支持中文和其他编码
* @static
* @access public
* @param string $str 需要转换的字符串
* @param string $start 开始位置
* @param string $length 截取长度
* @param string $charset 编码格式
* @param string $suffix 截断显示字符
* @return string
*/
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
if(function_exists("mb_substr"))
$slice = mb_substr($str, $start, $length, $charset);
elseif(function_exists('iconv_substr')) {
$slice = iconv_substr($str,$start,$length,$charset);
if(false === $slice) {
$slice = '';
}
}else{
$re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
$re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
$re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
preg_match_all($re[$charset], $str, $match);
$slice = join("",array_slice($match[0], $start, $length));
}
return $suffix ? $slice.'...' : $slice;
}
/**
* 产生随机字串,可用来自动生成密码 默认长度6位 字母和数字混合
* @param string $len 长度
* @param string $type 字串类型
* 0 字母 1 数字 其它 混合
* @param string $addChars 额外字符
* @return string
*/
function rand_string($len=6,$type='',$addChars='') {
$str ='';
switch($type) {
case 0:
$chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.$addChars;
break;
case 1:
$chars= str_repeat('0123456789',3);
break;
case 2:
$chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.$addChars;
break;
case 3:
$chars='abcdefghijklmnopqrstuvwxyz'.$addChars;
break;
case 4:
$chars = "们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借".$addChars;
break;
default :
// 默认去掉了容易混淆的字符oOLl和数字01,要添加请使用addChars参数
$chars='ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789'.$addChars;
break;
}
if($len>10 ) {//位数过长重复字符串一定次数
$chars= $type==1? str_repeat($chars,$len) : str_repeat($chars,5);
}
if($type!=4) {
$chars = str_shuffle($chars);
$str = substr($chars,0,$len);
}else{
// 中文随机字
for($i=0;$i<$len;$i++){
$str.= msubstr($chars, floor(mt_rand(0,mb_strlen($chars,'utf-8')-1)),1);
}
}
return $str;
}
/**
* 获取登录验证码 默认为4位数字
* @param string $fmode 文件名
* @return string
*/
function build_verify ($length=4,$mode=1) {
return rand_string($length,$mode);
}
/**
* 字节格式化 把字节数格式为 B K M G T 描述的大小
* @return string
*/
function byte_format($size, $dec=2) {
$a = array("B", "KB", "MB", "GB", "TB", "PB");
$pos = 0;
while ($size >= 1024) {
$size /= 1024;
$pos++;
}
return round($size,$dec)." ".$a[$pos];
}
/**
* 检查字符串是否是UTF8编码
* @param string $string 字符串
* @return Boolean
*/
function is_utf8($string) {
return preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $string);
}
/**
* 代码加亮
* @param String $str 要高亮显示的字符串 或者 文件名
* @param Boolean $show 是否输出
* @return String
*/
function highlight_code($str,$show=false) {
if(file_exists($str)) {
$str = file_get_contents($str);
}
$str = stripslashes(trim($str));
// The highlight string function encodes and highlights
// brackets so we need them to start raw
$str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
// Replace any existing PHP tags to temporary markers so they don't accidentally
// break the string out of PHP, and thus, thwart the highlighting.
$str = str_replace(array('&lt;?php', '?&gt;', '\\'), array('phptagopen', 'phptagclose', 'backslashtmp'), $str);
// The highlight_string function requires that the text be surrounded
// by PHP tags. Since we don't know if A) the submitted text has PHP tags,
// or B) whether the PHP tags enclose the entire string, we will add our
// own PHP tags around the string along with some markers to make replacement easier later
$str = '<?php //tempstart'."\n".$str.'//tempend ?>'; // <?
// All the magic happens here, baby!
$str = highlight_string($str, TRUE);
// Prior to PHP 5, the highlight function used icky font tags
// so we'll replace them with span tags.
if (abs(phpversion()) < 5) {
$str = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $str);
$str = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
}
// Remove our artificially added PHP
$str = preg_replace("#\<code\>.+?//tempstart\<br />\</span\>#is", "<code>\n", $str);
$str = preg_replace("#\<code\>.+?//tempstart\<br />#is", "<code>\n", $str);
$str = preg_replace("#//tempend.+#is", "</span>\n</code>", $str);
// Replace our markers back to PHP tags.
$str = str_replace(array('phptagopen', 'phptagclose', 'backslashtmp'), array('&lt;?php', '?&gt;', '\\'), $str); //<?
$line = explode("<br />", rtrim(ltrim($str,'<code>'),'</code>'));
$result = '<div class="code"><ol>';
foreach($line as $key=>$val) {
$result .= '<li>'.$val.'</li>';
}
$result .= '</ol></div>';
$result = str_replace("\n", "", $result);
if( $show!== false) {
echo($result);
}else {
return $result;
}
}
//输出安全的html
function h($text, $tags = null) {
$text = trim($text);
//完全过滤注释
$text = preg_replace('/<!--?.*-->/','',$text);
//完全过滤动态代码
$text = preg_replace('/<\?|\?'.'>/','',$text);
//完全过滤js
$text = preg_replace('/<script?.*\/script>/','',$text);
$text = str_replace('[','&#091;',$text);
$text = str_replace(']','&#093;',$text);
$text = str_replace('|','&#124;',$text);
//过滤换行符
$text = preg_replace('/\r?\n/','',$text);
//br
$text = preg_replace('/<br(\s\/)?'.'>/i','[br]',$text);
$text = preg_replace('/<p(\s\/)?'.'>/i','[br]',$text);
$text = preg_replace('/(\[br\]\s*){10,}/i','[br]',$text);
//过滤危险的属性,如:过滤on事件lang js
while(preg_match('/(<[^><]+)( lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){
$text=str_replace($mat[0],$mat[1],$text);
}
while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
$text=str_replace($mat[0],$mat[1].$mat[3],$text);
}
if(empty($tags)) {
$tags = 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a';
}
//允许的HTML标签
$text = preg_replace('/<('.$tags.')( [^><\[\]]*)>/i','[\1\2]',$text);
$text = preg_replace('/<\/('.$tags.')>/Ui','[/\1]',$text);
//过滤多余html
$text = preg_replace('/<\/?(html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml)[^><]*>/i','',$text);
//过滤合法的html标签
while(preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i',$text,$mat)){
$text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text);
}
//转换引号
while(preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i',$text,$mat)){
$text=str_replace($mat[0],$mat[1].'|'.$mat[3].'|'.$mat[4],$text);
}
//过滤错误的单个引号
while(preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i',$text,$mat)){
$text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text);
}
//转换其它所有不合法的 < >
$text = str_replace('<','&lt;',$text);
$text = str_replace('>','&gt;',$text);
$text = str_replace('"','&quot;',$text);
//反转换
$text = str_replace('[','<',$text);
$text = str_replace(']','>',$text);
$text = str_replace('|','"',$text);
//过滤多余空格
$text = str_replace(' ',' ',$text);
return $text;
}
function ubb($Text) {
$Text=trim($Text);
//$Text=htmlspecialchars($Text);
$Text=preg_replace("/\\t/is"," ",$Text);
$Text=preg_replace("/\[h1\](.+?)\[\/h1\]/is","<h1>\\1</h1>",$Text);
$Text=preg_replace("/\[h2\](.+?)\[\/h2\]/is","<h2>\\1</h2>",$Text);
$Text=preg_replace("/\[h3\](.+?)\[\/h3\]/is","<h3>\\1</h3>",$Text);
$Text=preg_replace("/\[h4\](.+?)\[\/h4\]/is","<h4>\\1</h4>",$Text);
$Text=preg_replace("/\[h5\](.+?)\[\/h5\]/is","<h5>\\1</h5>",$Text);
$Text=preg_replace("/\[h6\](.+?)\[\/h6\]/is","<h6>\\1</h6>",$Text);
$Text=preg_replace("/\[separator\]/is","",$Text);
$Text=preg_replace("/\[center\](.+?)\[\/center\]/is","<center>\\1</center>",$Text);
$Text=preg_replace("/\[url=http:\/\/([^\[]*)\](.+?)\[\/url\]/is","<a href=\"http://\\1\" target=_blank>\\2</a>",$Text);
$Text=preg_replace("/\[url=([^\[]*)\](.+?)\[\/url\]/is","<a href=\"http://\\1\" target=_blank>\\2</a>",$Text);
$Text=preg_replace("/\[url\]http:\/\/([^\[]*)\[\/url\]/is","<a href=\"http://\\1\" target=_blank>\\1</a>",$Text);
$Text=preg_replace("/\[url\]([^\[]*)\[\/url\]/is","<a href=\"\\1\" target=_blank>\\1</a>",$Text);
$Text=preg_replace("/\[img\](.+?)\[\/img\]/is","<img src=\\1>",$Text);
$Text=preg_replace("/\[color=(.+?)\](.+?)\[\/color\]/is","<font color=\\1>\\2</font>",$Text);
$Text=preg_replace("/\[size=(.+?)\](.+?)\[\/size\]/is","<font size=\\1>\\2</font>",$Text);
$Text=preg_replace("/\[sup\](.+?)\[\/sup\]/is","<sup>\\1</sup>",$Text);
$Text=preg_replace("/\[sub\](.+?)\[\/sub\]/is","<sub>\\1</sub>",$Text);
$Text=preg_replace("/\[pre\](.+?)\[\/pre\]/is","<pre>\\1</pre>",$Text);
$Text=preg_replace("/\[email\](.+?)\[\/email\]/is","<a href='mailto:\\1'>\\1</a>",$Text);
$Text=preg_replace("/\[colorTxt\](.+?)\[\/colorTxt\]/eis","color_txt('\\1')",$Text);
$Text=preg_replace("/\[emot\](.+?)\[\/emot\]/eis","emot('\\1')",$Text);
$Text=preg_replace("/\[i\](.+?)\[\/i\]/is","<i>\\1</i>",$Text);
$Text=preg_replace("/\[u\](.+?)\[\/u\]/is","<u>\\1</u>",$Text);
$Text=preg_replace("/\[b\](.+?)\[\/b\]/is","<b>\\1</b>",$Text);
$Text=preg_replace("/\[quote\](.+?)\[\/quote\]/is"," <div class='quote'><h5>引用:</h5><blockquote>\\1</blockquote></div>", $Text);
$Text=preg_replace("/\[code\](.+?)\[\/code\]/eis","highlight_code('\\1')", $Text);
$Text=preg_replace("/\[php\](.+?)\[\/php\]/eis","highlight_code('\\1')", $Text);
$Text=preg_replace("/\[sig\](.+?)\[\/sig\]/is","<div class='sign'>\\1</div>", $Text);
$Text=preg_replace("/\\n/is","<br/>",$Text);
return $Text;
}
// 随机生成一组字符串
function build_count_rand ($number,$length=4,$mode=1) {
if($mode==1 && $length<strlen($number) ) {
//不足以生成一定数量的不重复数字
return false;
}
$rand = array();
for($i=0; $i<$number; $i++) {
$rand[] = rand_string($length,$mode);
}
$unqiue = array_unique($rand);
if(count($unqiue)==count($rand)) {
return $rand;
}
$count = count($rand)-count($unqiue);
for($i=0; $i<$count*3; $i++) {
$rand[] = rand_string($length,$mode);
}
$rand = array_slice(array_unique ($rand),0,$number);
return $rand;
}
function remove_xss($val) {
// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
// this prevents some character re-spacing such as <java\0script>
// note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
$val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);
// straight replacements, the user should never need these since they're normal characters
// this prevents like <IMG SRC=@avascript:alert('XSS')>
$search = 'abcdefghijklmnopqrstuvwxyz';
$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$search .= '1234567890!@#$%^&*()';
$search .= '~`";:?+/={}[]-_|\'\\';
for ($i = 0; $i < strlen($search); $i++) {
// ;? matches the ;, which is optional
// 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
// @ @ search for the hex values
$val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
// @ @ 0{0,7} matches '0' zero to seven times
$val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
}
// now the only remaining whitespace attacks are \t, \n, and \r
$ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
$ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
$ra = array_merge($ra1, $ra2);
$found = true; // keep replacing as long as the previous round replaced something
while ($found == true) {
$val_before = $val;
for ($i = 0; $i < sizeof($ra); $i++) {
$pattern = '/';
for ($j = 0; $j < strlen($ra[$i]); $j++) {
if ($j > 0) {
$pattern .= '(';
$pattern .= '(&#[xX]0{0,8}([9ab]);)';
$pattern .= '|';
$pattern .= '|(&#0{0,8}([9|10|13]);)';
$pattern .= ')*';
}
$pattern .= $ra[$i][$j];
}
$pattern .= '/i';
$replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
$val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
if ($val_before == $val) {
// no replacements were made, so exit the loop
$found = false;
}
}
}
return $val;
}
/**
* 把返回的数据集转换成Tree
* @access public
* @param array $list 要转换的数据集
* @param string $pid parent标记字段
* @param string $level level标记字段
* @return array
*/
function list_to_tree($list, $pk='id',$pid = 'pid',$child = '_child',$root=0) {
// 创建Tree
$tree = array();
if(is_array($list)) {
// 创建基于主键的数组引用
$refer = array();
foreach ($list as $key => $data) {
$refer[$data[$pk]] =& $list[$key];
}
foreach ($list as $key => $data) {
// 判断是否存在parent
$parentId = $data[$pid];
if ($root == $parentId) {
$tree[] =& $list[$key];
}else{
if (isset($refer[$parentId])) {
$parent =& $refer[$parentId];
$parent[$child][] =& $list[$key];
}
}
}
}
return $tree;
}
/**
* 对查询结果集进行排序
* @access public
* @param array $list 查询结果
* @param string $field 排序的字段名
* @param array $sortby 排序类型
* asc正向排序 desc逆向排序 nat自然排序
* @return array
*/
function list_sort_by($list,$field, $sortby='asc') {
if(is_array($list)){
$refer = $resultSet = array();
foreach ($list as $i => $data)
$refer[$i] = &$data[$field];
switch ($sortby) {
case 'asc': // 正向排序
asort($refer);
break;
case 'desc':// 逆向排序
arsort($refer);
break;
case 'nat': // 自然排序
natcasesort($refer);
break;
}
foreach ( $refer as $key=> $val)
$resultSet[] = &$list[$key];
return $resultSet;
}
return false;
}
/**
* 在数据列表中搜索
* @access public
* @param array $list 数据列表
* @param mixed $condition 查询条件
* 支持 array('name'=>$value) 或者 name=$value
* @return array
*/
function list_search($list,$condition) {
if(is_string($condition))
parse_str($condition,$condition);
// 返回的结果集合
$resultSet = array();
foreach ($list as $key=>$data){
$find = false;
foreach ($condition as $field=>$value){
if(isset($data[$field])) {
if(0 === strpos($value,'/')) {
$find = preg_match($value,$data[$field]);
}elseif($data[$field]==$value){
$find = true;
}
}
}
if($find)
$resultSet[] = &$list[$key];
}
return $resultSet;
}
// 自动转换字符集 支持数组转换
function auto_charset($fContents, $from='gbk', $to='utf-8') {
$from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from;
$to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to;
if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) {
//如果编码相同或者非字符串标量则不转换
return $fContents;
}
if (is_string($fContents)) {
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($fContents, $to, $from);
} elseif (function_exists('iconv')) {
return iconv($from, $to, $fContents);
} else {
return $fContents;
}
} elseif (is_array($fContents)) {
foreach ($fContents as $key => $val) {
$_key = auto_charset($key, $from, $to);
$fContents[$_key] = auto_charset($val, $from, $to);
if ($key != $_key)
unset($fContents[$key]);
}
return $fContents;
}
else {
return $fContents;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Base64 加密实现类
* @category ORG
* @package ORG
* @subpackage Crypt
* @author liu21st <liu21st@gmail.com>
*/
class Base64 {
/**
* 加密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
public static function encrypt($data,$key) {
$key = md5($key);
$data = base64_encode($data);
$x=0;
$len = strlen($data);
$l = strlen($key);
for ($i=0;$i< $len;$i++) {
if ($x== $l) $x=0;
$char .=substr($key,$x,1);
$x++;
}
for ($i=0;$i< $len;$i++) {
$str .=chr(ord(substr($data,$i,1))+(ord(substr($char,$i,1)))%256);
}
return $str;
}
/**
* 解密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
public static function decrypt($data,$key) {
$key = md5($key);
$x=0;
$len = strlen($data);
$l = strlen($key);
for ($i=0;$i< $len;$i++) {
if ($x== $l) $x=0;
$char .=substr($key,$x,1);
$x++;
}
for ($i=0;$i< $len;$i++) {
if (ord(substr($data,$i,1))<ord(substr($char,$i,1))) {
$str .=chr((ord(substr($data,$i,1))+256)-ord(substr($char,$i,1)));
}else{
$str .=chr(ord(substr($data,$i,1))-ord(substr($char,$i,1)));
}
}
return base64_decode($str);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Crypt 加密实现类
* @category ORG
* @package ORG
* @subpackage Crypt
* @author liu21st <liu21st@gmail.com>
*/
class Crypt {
/**
* 加密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
function encrypt($str,$key,$toBase64=false){
$r = md5($key);
$c=0;
$v = "";
$len = strlen($str);
$l = strlen($r);
for ($i=0;$i<$len;$i++){
if ($c== $l) $c=0;
$v.= substr($r,$c,1) .
(substr($str,$i,1) ^ substr($r,$c,1));
$c++;
}
if($toBase64) {
return base64_encode(self::ed($v,$key));
}else {
return self::ed($v,$key);
}
}
/**
* 解密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
function decrypt($str,$key,$toBase64=false) {
if($toBase64) {
$str = self::ed(base64_decode($str),$key);
}else {
$str = self::ed($str,$key);
}
$v = "";
$len = strlen($str);
for ($i=0;$i<$len;$i++){
$md5 = substr($str,$i,1);
$i++;
$v.= (substr($str,$i,1) ^ $md5);
}
return $v;
}
function ed($str,$key) {
$r = md5($key);
$c=0;
$v = "";
$len = strlen($str);
$l = strlen($r);
for ($i=0;$i<$len;$i++) {
if ($c==$l) $c=0;
$v.= substr($str,$i,1) ^ substr($r,$c,1);
$c++;
}
return $v;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Des 加密实现类
* Converted from JavaScript to PHP by Jim Gibbs, June 2004 Paul Tero, July 2001
* Optimised for performance with large blocks by Michael Hayworth, November 2001
* http://www.netdealing.com
* @category ORG
* @package ORG
* @subpackage Crypt
* @author liu21st <liu21st@gmail.com>
*/
class Des {
/**
* 加密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
function encrypt($str, $key) {
if ($str == "") {
return "";
}
return self::_des($key,$str,1);
}
/**
* 解密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
function decrypt($str, $key) {
if ($str == "") {
return "";
}
return self::_des($key,$str,0);
}
/**
* Des算法
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
function _des($key, $message, $encrypt, $mode=0, $iv=null) {
//declaring this locally speeds things up a bit
$spfunction1 = array (0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004);
$spfunction2 = array (-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000);
$spfunction3 = array (0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200);
$spfunction4 = array (0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080);
$spfunction5 = array (0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100);
$spfunction6 = array (0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010);
$spfunction7 = array (0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002);
$spfunction8 = array (0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000);
$masks = array (4294967295,2147483647,1073741823,536870911,268435455,134217727,67108863,33554431,16777215,8388607,4194303,2097151,1048575,524287,262143,131071,65535,32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1,0);
//create the 16 or 48 subkeys we will need
$keys = self::_createKeys ($key);
$m=0;
$len = strlen($message);
$chunk = 0;
//set up the loops for single and triple des
$iterations = ((count($keys) == 32) ? 3 : 9); //single or triple des
if ($iterations == 3) {$looping = (($encrypt) ? array (0, 32, 2) : array (30, -2, -2));}
else {$looping = (($encrypt) ? array (0, 32, 2, 62, 30, -2, 64, 96, 2) : array (94, 62, -2, 32, 64, 2, 30, -2, -2));}
$message .= (chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0)); //pad the message out with null bytes
//store the result here
$result = "";
$tempresult = "";
if ($mode == 1) { //CBC mode
$cbcleft = (ord($iv{$m++}) << 24) | (ord($iv{$m++}) << 16) | (ord($iv{$m++}) << 8) | ord($iv{$m++});
$cbcright = (ord($iv{$m++}) << 24) | (ord($iv{$m++}) << 16) | (ord($iv{$m++}) << 8) | ord($iv{$m++});
$m=0;
}
//loop through each 64 bit chunk of the message
while ($m < $len) {
$left = (ord($message{$m++}) << 24) | (ord($message{$m++}) << 16) | (ord($message{$m++}) << 8) | ord($message{$m++});
$right = (ord($message{$m++}) << 24) | (ord($message{$m++}) << 16) | (ord($message{$m++}) << 8) | ord($message{$m++});
//for Cipher Block Chaining mode, xor the message with the previous result
if ($mode == 1) {if ($encrypt) {$left ^= $cbcleft; $right ^= $cbcright;} else {$cbcleft2 = $cbcleft; $cbcright2 = $cbcright; $cbcleft = $left; $cbcright = $right;}}
//first each 64 but chunk of the message must be permuted according to IP
$temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f; $right ^= $temp; $left ^= ($temp << 4);
$temp = (($left >> 16 & $masks[16]) ^ $right) & 0x0000ffff; $right ^= $temp; $left ^= ($temp << 16);
$temp = (($right >> 2 & $masks[2]) ^ $left) & 0x33333333; $left ^= $temp; $right ^= ($temp << 2);
$temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff; $left ^= $temp; $right ^= ($temp << 8);
$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
$left = (($left << 1) | ($left >> 31 & $masks[31]));
$right = (($right << 1) | ($right >> 31 & $masks[31]));
//do this either 1 or 3 times for each chunk of the message
for ($j=0; $j<$iterations; $j+=3) {
$endloop = $looping[$j+1];
$loopinc = $looping[$j+2];
//now go through and perform the encryption or decryption
for ($i=$looping[$j]; $i!=$endloop; $i+=$loopinc) { //for efficiency
$right1 = $right ^ $keys[$i];
$right2 = (($right >> 4 & $masks[4]) | ($right << 28)) ^ $keys[$i+1];
//the result is attained by passing these bytes through the S selection functions
$temp = $left;
$left = $right;
$right = $temp ^ ($spfunction2[($right1 >> 24 & $masks[24]) & 0x3f] | $spfunction4[($right1 >> 16 & $masks[16]) & 0x3f]
| $spfunction6[($right1 >> 8 & $masks[8]) & 0x3f] | $spfunction8[$right1 & 0x3f]
| $spfunction1[($right2 >> 24 & $masks[24]) & 0x3f] | $spfunction3[($right2 >> 16 & $masks[16]) & 0x3f]
| $spfunction5[($right2 >> 8 & $masks[8]) & 0x3f] | $spfunction7[$right2 & 0x3f]);
}
$temp = $left; $left = $right; $right = $temp; //unreverse left and right
} //for either 1 or 3 iterations
//move then each one bit to the right
$left = (($left >> 1 & $masks[1]) | ($left << 31));
$right = (($right >> 1 & $masks[1]) | ($right << 31));
//now perform IP-1, which is IP in the opposite direction
$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
$temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff; $left ^= $temp; $right ^= ($temp << 8);
$temp = (($right >> 2 & $masks[2]) ^ $left) & 0x33333333; $left ^= $temp; $right ^= ($temp << 2);
$temp = (($left >> 16 & $masks[16]) ^ $right) & 0x0000ffff; $right ^= $temp; $left ^= ($temp << 16);
$temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f; $right ^= $temp; $left ^= ($temp << 4);
//for Cipher Block Chaining mode, xor the message with the previous result
if ($mode == 1) {if ($encrypt) {$cbcleft = $left; $cbcright = $right;} else {$left ^= $cbcleft2; $right ^= $cbcright2;}}
$tempresult .= (chr($left>>24 & $masks[24]) . chr(($left>>16 & $masks[16]) & 0xff) . chr(($left>>8 & $masks[8]) & 0xff) . chr($left & 0xff) . chr($right>>24 & $masks[24]) . chr(($right>>16 & $masks[16]) & 0xff) . chr(($right>>8 & $masks[8]) & 0xff) . chr($right & 0xff));
$chunk += 8;
if ($chunk == 512) {$result .= $tempresult; $tempresult = ""; $chunk = 0;}
} //for every 8 characters, or 64 bits in the message
//return the result as an array
return ($result . $tempresult);
} //end of des
/**
* createKeys
* this takes as input a 64 bit key (even though only 56 bits are used)
* as an array of 2 integers, and returns 16 48 bit keys
* @access static
* @param string $key 加密key
* @return string
*/
function _createKeys ($key) {
//declaring this locally speeds things up a bit
$pc2bytes0 = array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
$pc2bytes1 = array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
$pc2bytes2 = array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
$pc2bytes3 = array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
$pc2bytes4 = array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
$pc2bytes5 = array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
$pc2bytes6 = array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
$pc2bytes7 = array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
$pc2bytes8 = array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
$pc2bytes9 = array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
$pc2bytes10 = array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
$pc2bytes11 = array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
$pc2bytes12 = array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
$pc2bytes13 = array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);
$masks = array (4294967295,2147483647,1073741823,536870911,268435455,134217727,67108863,33554431,16777215,8388607,4194303,2097151,1048575,524287,262143,131071,65535,32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1,0);
//how many iterations (1 for des, 3 for triple des)
$iterations = ((strlen($key) >= 24) ? 3 : 1);
//stores the return keys
$keys = array (); // size = 32 * iterations but you don't specify this in php
//now define the left shifts which need to be done
$shifts = array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
//other variables
$m=0;
$n=0;
for ($j=0; $j<$iterations; $j++) { //either 1 or 3 iterations
$left = (ord($key{$m++}) << 24) | (ord($key{$m++}) << 16) | (ord($key{$m++}) << 8) | ord($key{$m++});
$right = (ord($key{$m++}) << 24) | (ord($key{$m++}) << 16) | (ord($key{$m++}) << 8) | ord($key{$m++});
$temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f; $right ^= $temp; $left ^= ($temp << 4);
$temp = (($right >> 16 & $masks[16]) ^ $left) & 0x0000ffff; $left ^= $temp; $right ^= ($temp << -16);
$temp = (($left >> 2 & $masks[2]) ^ $right) & 0x33333333; $right ^= $temp; $left ^= ($temp << 2);
$temp = (($right >> 16 & $masks[16]) ^ $left) & 0x0000ffff; $left ^= $temp; $right ^= ($temp << -16);
$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
$temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff; $left ^= $temp; $right ^= ($temp << 8);
$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
//the right side needs to be shifted and to get the last four bits of the left side
$temp = ($left << 8) | (($right >> 20 & $masks[20]) & 0x000000f0);
//left needs to be put upside down
$left = ($right << 24) | (($right << 8) & 0xff0000) | (($right >> 8 & $masks[8]) & 0xff00) | (($right >> 24 & $masks[24]) & 0xf0);
$right = $temp;
//now go through and perform these shifts on the left and right keys
for ($i=0; $i < count($shifts); $i++) {
//shift the keys either one or two bits to the left
if ($shifts[$i] > 0) {
$left = (($left << 2) | ($left >> 26 & $masks[26]));
$right = (($right << 2) | ($right >> 26 & $masks[26]));
} else {
$left = (($left << 1) | ($left >> 27 & $masks[27]));
$right = (($right << 1) | ($right >> 27 & $masks[27]));
}
$left = $left & -0xf;
$right = $right & -0xf;
//now apply PC-2, in such a way that E is easier when encrypting or decrypting
//this conversion will look like PC-2 except only the last 6 bits of each byte are used
//rather than 48 consecutive bits and the order of lines will be according to
//how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
$lefttemp = $pc2bytes0[$left >> 28 & $masks[28]] | $pc2bytes1[($left >> 24 & $masks[24]) & 0xf]
| $pc2bytes2[($left >> 20 & $masks[20]) & 0xf] | $pc2bytes3[($left >> 16 & $masks[16]) & 0xf]
| $pc2bytes4[($left >> 12 & $masks[12]) & 0xf] | $pc2bytes5[($left >> 8 & $masks[8]) & 0xf]
| $pc2bytes6[($left >> 4 & $masks[4]) & 0xf];
$righttemp = $pc2bytes7[$right >> 28 & $masks[28]] | $pc2bytes8[($right >> 24 & $masks[24]) & 0xf]
| $pc2bytes9[($right >> 20 & $masks[20]) & 0xf] | $pc2bytes10[($right >> 16 & $masks[16]) & 0xf]
| $pc2bytes11[($right >> 12 & $masks[12]) & 0xf] | $pc2bytes12[($right >> 8 & $masks[8]) & 0xf]
| $pc2bytes13[($right >> 4 & $masks[4]) & 0xf];
$temp = (($righttemp >> 16 & $masks[16]) ^ $lefttemp) & 0x0000ffff;
$keys[$n++] = $lefttemp ^ $temp; $keys[$n++] = $righttemp ^ ($temp << 16);
}
} //for each iterations
//return the keys we've created
return $keys;
} //end of des_createKeys
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: cevin <cevin1991@gmail.com>
// +----------------------------------------------------------------------
/**
* HMAC 加密实现类
* @category ORG
* @package ORG
* @subpackage Crypt
* @author cevin <cevin1991@gmail.com>
*/
class Hmac {
/**
* SHA1加密
* @access static
* @param string $key 加密key
* @param string $str 字符串
* @return string
*/
public static function sha1($key,$str) {
$blocksize=64;
$hashfunc='sha1';
if (strlen($key)>$blocksize)
$key=pack('H*', $hashfunc($key));
$key=str_pad($key,$blocksize,chr(0x00));
$ipad=str_repeat(chr(0x36),$blocksize);
$opad=str_repeat(chr(0x5c),$blocksize);
$hmac = pack(
'H*',$hashfunc(
($key^$opad).pack(
'H*',$hashfunc(
($key^$ipad).$str
)
)
)
);
return $hmac;
}
/**
* MD5加密
* @access static
* @param string $key 加密key
* @param string $str 字符串
* @return string
*/
public static function md5($key, $str) {
$b = 64;
if (strlen($key) > $b) {
$key = pack("H*",md5($key));
}
$key = str_pad($key, $b, chr(0x00));
$ipad = str_pad('', $b, chr(0x36));
$opad = str_pad('', $b, chr(0x5c));
$k_ipad = $key ^ $ipad ;
$k_opad = $key ^ $opad;
return md5($k_opad . pack("H*",md5($k_ipad . $str)));
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
define("BCCOMP_LARGER", 1);
/**
* Rsa 加密实现类
* @category ORG
* @package ORG
* @subpackage Crypt
* @author liu21st <liu21st@gmail.com>
*/
class Rsa {
/**
* 加密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
public static function encrypt($message, $public_key, $modulus, $keylength) {
$padded = self::add_PKCS1_padding($message, true, $keylength / 8);
$number = self::binary_to_number($padded);
$encrypted = self::pow_mod($number, $public_key, $modulus);
$result = self::number_to_binary($encrypted, $keylength / 8);
return $result;
}
/**
* 解密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
public static function decrypt($message, $private_key, $modulus, $keylength) {
$number = self::binary_to_number($message);
$decrypted = self::pow_mod($number, $private_key, $modulus);
$result = self::number_to_binary($decrypted, $keylength / 8);
return self::remove_PKCS1_padding($result, $keylength / 8);
}
function sign($message, $private_key, $modulus, $keylength) {
$padded = self::add_PKCS1_padding($message, false, $keylength / 8);
$number = self::binary_to_number($padded);
$signed = self::pow_mod($number, $private_key, $modulus);
$result = self::number_to_binary($signed, $keylength / 8);
return $result;
}
function verify($message, $public_key, $modulus, $keylength) {
return decrypt($message, $public_key, $modulus, $keylength);
}
function pow_mod($p, $q, $r) {
// Extract powers of 2 from $q
$factors = array();
$div = $q;
$power_of_two = 0;
while(bccomp($div, "0") == BCCOMP_LARGER)
{
$rem = bcmod($div, 2);
$div = bcdiv($div, 2);
if($rem) array_push($factors, $power_of_two);
$power_of_two++;
}
// Calculate partial results for each factor, using each partial result as a
// starting point for the next. This depends of the factors of two being
// generated in increasing order.
$partial_results = array();
$part_res = $p;
$idx = 0;
foreach($factors as $factor)
{
while($idx < $factor)
{
$part_res = bcpow($part_res, "2");
$part_res = bcmod($part_res, $r);
$idx++;
}
array_push($partial_results, $part_res);
}
// Calculate final result
$result = "1";
foreach($partial_results as $part_res)
{
$result = bcmul($result, $part_res);
$result = bcmod($result, $r);
}
return $result;
}
//--
// Function to add padding to a decrypted string
// We need to know if this is a private or a public key operation [4]
//--
function add_PKCS1_padding($data, $isPublicKey, $blocksize) {
$pad_length = $blocksize - 3 - strlen($data);
if($isPublicKey)
{
$block_type = "\x02";
$padding = "";
for($i = 0; $i < $pad_length; $i++)
{
$rnd = mt_rand(1, 255);
$padding .= chr($rnd);
}
}
else
{
$block_type = "\x01";
$padding = str_repeat("\xFF", $pad_length);
}
return "\x00" . $block_type . $padding . "\x00" . $data;
}
//--
// Remove padding from a decrypted string
// See [4] for more details.
//--
function remove_PKCS1_padding($data, $blocksize) {
assert(strlen($data) == $blocksize);
$data = substr($data, 1);
// We cannot deal with block type 0
if($data{0} == '\0')
die("Block type 0 not implemented.");
// Then the block type must be 1 or 2
assert(($data{0} == "\x01") || ($data{0} == "\x02"));
// Remove the padding
$offset = strpos($data, "\0", 1);
return substr($data, $offset + 1);
}
//--
// Convert binary data to a decimal number
//--
function binary_to_number($data) {
$base = "256";
$radix = "1";
$result = "0";
for($i = strlen($data) - 1; $i >= 0; $i--)
{
$digit = ord($data{$i});
$part_res = bcmul($digit, $radix);
$result = bcadd($result, $part_res);
$radix = bcmul($radix, $base);
}
return $result;
}
//--
// Convert a number back into binary form
//--
function number_to_binary($number, $blocksize) {
$base = "256";
$result = "";
$div = $number;
while($div > 0)
{
$mod = bcmod($div, $base);
$div = bcdiv($div, $base);
$result = chr($mod) . $result;
}
return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Xxtea 加密实现类
* @category ORG
* @package ORG
* @subpackage Crypt
* @author liu21st <liu21st@gmail.com>
*/
class Xxtea {
/**
* 加密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
public static function encrypt($str, $key) {
if ($str == "") {
return "";
}
$v = self::str2long($str, true);
$k = self::str2long($key, false);
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = 0;
while (0 < $q--) {
$sum = self::int32($sum + $delta);
$e = $sum >> 2 & 3;
for ($p = 0; $p < $n; $p++) {
$y = $v[$p + 1];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$p] = self::int32($v[$p] + $mx);
}
$y = $v[0];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$n] = self::int32($v[$n] + $mx);
}
return self::long2str($v, false);
}
/**
* 解密字符串
* @access static
* @param string $str 字符串
* @param string $key 加密key
* @return string
*/
public static function decrypt($str, $key) {
if ($str == "") {
return "";
}
$v = self::str2long($str, false);
$k = self::str2long($key, false);
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = self::int32($q * $delta);
while ($sum != 0) {
$e = $sum >> 2 & 3;
for ($p = $n; $p > 0; $p--) {
$z = $v[$p - 1];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$y = $v[$p] = self::int32($v[$p] - $mx);
}
$z = $v[$n];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$y = $v[0] = self::int32($v[0] - $mx);
$sum = self::int32($sum - $delta);
}
return self::long2str($v, true);
}
private static function long2str($v, $w) {
$len = count($v);
$s = array();
for ($i = 0; $i < $len; $i++) {
$s[$i] = pack("V", $v[$i]);
}
if ($w) {
return substr(join('', $s), 0, $v[$len - 1]);
}else{
return join('', $s);
}
}
private static function str2long($s, $w) {
$v = unpack("V*", $s. str_repeat("\0", (4 - strlen($s) % 4) & 3));
$v = array_values($v);
if ($w) {
$v[count($v)] = strlen($s);
}
return $v;
}
private static function int32($n) {
while ($n >= 2147483648) $n -= 4294967296;
while ($n <= -2147483649) $n += 4294967296;
return (int)$n;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* Http 工具类
* 提供一系列的Http方法
* @category ORG
* @package ORG
* @subpackage Net
* @author liu21st <liu21st@gmail.com>
*/
class Http {
/**
* 采集远程文件
* @access public
* @param string $remote 远程文件名
* @param string $local 本地保存文件名
* @return mixed
*/
static public function curlDownload($remote,$local) {
$cp = curl_init($remote);
$fp = fopen($local,"w");
curl_setopt($cp, CURLOPT_FILE, $fp);
curl_setopt($cp, CURLOPT_HEADER, 0);
curl_exec($cp);
curl_close($cp);
fclose($fp);
}
/**
* 使用 fsockopen 通过 HTTP 协议直接访问(采集)远程文件
* 如果主机或服务器没有开启 CURL 扩展可考虑使用
* fsockopen 比 CURL 稍慢,但性能稳定
* @static
* @access public
* @param string $url 远程URL
* @param array $conf 其他配置信息
* int limit 分段读取字符个数
* string post post的内容,字符串或数组,key=value&形式
* string cookie 携带cookie访问,该参数是cookie内容
* string ip 如果该参数传入,$url将不被使用,ip访问优先
* int timeout 采集超时时间
* bool block 是否阻塞访问,默认为true
* @return mixed
*/
static public function fsockopenDownload($url, $conf = array()) {
$return = '';
if(!is_array($conf)) return $return;
$matches = parse_url($url);
!isset($matches['host']) && $matches['host'] = '';
!isset($matches['path']) && $matches['path'] = '';
!isset($matches['query']) && $matches['query'] = '';
!isset($matches['port']) && $matches['port'] = '';
$host = $matches['host'];
$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
$port = !empty($matches['port']) ? $matches['port'] : 80;
$conf_arr = array(
'limit' => 0,
'post' => '',
'cookie' => '',
'ip' => '',
'timeout' => 15,
'block' => TRUE,
);
foreach (array_merge($conf_arr, $conf) as $k=>$v) ${$k} = $v;
if($post) {
if(is_array($post))
{
$post = http_build_query($post);
}
$out = "POST $path HTTP/1.0\r\n";
$out .= "Accept: */*\r\n";
//$out .= "Referer: $boardurl\r\n";
$out .= "Accept-Language: zh-cn\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
$out .= "Host: $host\r\n";
$out .= 'Content-Length: '.strlen($post)."\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cache-Control: no-cache\r\n";
$out .= "Cookie: $cookie\r\n\r\n";
$out .= $post;
} else {
$out = "GET $path HTTP/1.0\r\n";
$out .= "Accept: */*\r\n";
//$out .= "Referer: $boardurl\r\n";
$out .= "Accept-Language: zh-cn\r\n";
$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cookie: $cookie\r\n\r\n";
}
$fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
if(!$fp) {
return '';
} else {
stream_set_blocking($fp, $block);
stream_set_timeout($fp, $timeout);
@fwrite($fp, $out);
$status = stream_get_meta_data($fp);
if(!$status['timed_out']) {
while (!feof($fp)) {
if(($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n")) {
break;
}
}
$stop = false;
while(!feof($fp) && !$stop) {
$data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
$return .= $data;
if($limit) {
$limit -= strlen($data);
$stop = $limit <= 0;
}
}
}
@fclose($fp);
return $return;
}
}
/**
* 下载文件
* 可以指定下载显示的文件名,并自动发送相应的Header信息
* 如果指定了content参数,则下载该参数的内容
* @static
* @access public
* @param string $filename 下载文件名
* @param string $showname 下载显示的文件名
* @param string $content 下载的内容
* @param integer $expire 下载内容浏览器缓存时间
* @return void
*/
static public function download ($filename, $showname='',$content='',$expire=180) {
if(is_file($filename)) {
$length = filesize($filename);
}elseif(is_file(UPLOAD_PATH.$filename)) {
$filename = UPLOAD_PATH.$filename;
$length = filesize($filename);
}elseif($content != '') {
$length = strlen($content);
}else {
throw_exception($filename.L('下载文件不存在!'));
}
if(empty($showname)) {
$showname = $filename;
}
$showname = basename($showname);
if(!empty($filename)) {
$type = mime_content_type($filename);
}else{
$type = "application/octet-stream";
}
//发送Http Header信息 开始下载
header("Pragma: public");
header("Cache-control: max-age=".$expire);
//header('Cache-Control: no-store, no-cache, must-revalidate');
header("Expires: " . gmdate("D, d M Y H:i:s",time()+$expire) . "GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s",time()) . "GMT");
header("Content-Disposition: attachment; filename=".$showname);
header("Content-Length: ".$length);
header("Content-type: ".$type);
header('Content-Encoding: none');
header("Content-Transfer-Encoding: binary" );
if($content == '' ) {
readfile($filename);
}else {
echo($content);
}
exit();
}
/**
* 显示HTTP Header 信息
* @return string
*/
static function getHeaderInfo($header='',$echo=true) {
ob_start();
$headers = getallheaders();
if(!empty($header)) {
$info = $headers[$header];
echo($header.':'.$info."\n"); ;
}else {
foreach($headers as $key=>$val) {
echo("$key:$val\n");
}
}
$output = ob_get_clean();
if ($echo) {
echo (nl2br($output));
}else {
return $output;
}
}
/**
* HTTP Protocol defined status codes
* @param int $num
*/
static function sendHttpStatus($code) {
static $_status = array(
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
// Success 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found', // 1.1
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
// 306 is deprecated but reserved
307 => 'Temporary Redirect',
// Client Error 4xx
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
509 => 'Bandwidth Limit Exceeded'
);
if(isset($_status[$code])) {
header('HTTP/1.1 '.$code.' '.$_status[$code]);
}
}
}//类定义结束
if( !function_exists ('mime_content_type')) {
/**
* 获取文件的mime_content类型
* @return string
*/
function mime_content_type($filename) {
static $contentType = array(
'ai' => 'application/postscript',
'aif' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'asc' => 'application/pgp', //changed by skwashd - was text/plain
'asf' => 'video/x-ms-asf',
'asx' => 'video/x-ms-asf',
'au' => 'audio/basic',
'avi' => 'video/x-msvideo',
'bcpio' => 'application/x-bcpio',
'bin' => 'application/octet-stream',
'bmp' => 'image/bmp',
'c' => 'text/plain', // or 'text/x-csrc', //added by skwashd
'cc' => 'text/plain', // or 'text/x-c++src', //added by skwashd
'cs' => 'text/plain', //added by skwashd - for C# src
'cpp' => 'text/x-c++src', //added by skwashd
'cxx' => 'text/x-c++src', //added by skwashd
'cdf' => 'application/x-netcdf',
'class' => 'application/octet-stream',//secure but application/java-class is correct
'com' => 'application/octet-stream',//added by skwashd
'cpio' => 'application/x-cpio',
'cpt' => 'application/mac-compactpro',
'csh' => 'application/x-csh',
'css' => 'text/css',
'csv' => 'text/comma-separated-values',//added by skwashd
'dcr' => 'application/x-director',
'diff' => 'text/diff',
'dir' => 'application/x-director',
'dll' => 'application/octet-stream',
'dms' => 'application/octet-stream',
'doc' => 'application/msword',
'dot' => 'application/msword',//added by skwashd
'dvi' => 'application/x-dvi',
'dxr' => 'application/x-director',
'eps' => 'application/postscript',
'etx' => 'text/x-setext',
'exe' => 'application/octet-stream',
'ez' => 'application/andrew-inset',
'gif' => 'image/gif',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'h' => 'text/plain', // or 'text/x-chdr',//added by skwashd
'h++' => 'text/plain', // or 'text/x-c++hdr', //added by skwashd
'hh' => 'text/plain', // or 'text/x-c++hdr', //added by skwashd
'hpp' => 'text/plain', // or 'text/x-c++hdr', //added by skwashd
'hxx' => 'text/plain', // or 'text/x-c++hdr', //added by skwashd
'hdf' => 'application/x-hdf',
'hqx' => 'application/mac-binhex40',
'htm' => 'text/html',
'html' => 'text/html',
'ice' => 'x-conference/x-cooltalk',
'ics' => 'text/calendar',
'ief' => 'image/ief',
'ifb' => 'text/calendar',
'iges' => 'model/iges',
'igs' => 'model/iges',
'jar' => 'application/x-jar', //added by skwashd - alternative mime type
'java' => 'text/x-java-source', //added by skwashd
'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'js' => 'application/x-javascript',
'kar' => 'audio/midi',
'latex' => 'application/x-latex',
'lha' => 'application/octet-stream',
'log' => 'text/plain',
'lzh' => 'application/octet-stream',
'm3u' => 'audio/x-mpegurl',
'man' => 'application/x-troff-man',
'me' => 'application/x-troff-me',
'mesh' => 'model/mesh',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mif' => 'application/vnd.mif',
'mov' => 'video/quicktime',
'movie' => 'video/x-sgi-movie',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'mpe' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpga' => 'audio/mpeg',
'ms' => 'application/x-troff-ms',
'msh' => 'model/mesh',
'mxu' => 'video/vnd.mpegurl',
'nc' => 'application/x-netcdf',
'oda' => 'application/oda',
'patch' => 'text/diff',
'pbm' => 'image/x-portable-bitmap',
'pdb' => 'chemical/x-pdb',
'pdf' => 'application/pdf',
'pgm' => 'image/x-portable-graymap',
'pgn' => 'application/x-chess-pgn',
'pgp' => 'application/pgp',//added by skwashd
'php' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php3',
'pl' => 'application/x-perl',
'pm' => 'application/x-perl',
'png' => 'image/png',
'pnm' => 'image/x-portable-anymap',
'po' => 'text/plain',
'ppm' => 'image/x-portable-pixmap',
'ppt' => 'application/vnd.ms-powerpoint',
'ps' => 'application/postscript',
'qt' => 'video/quicktime',
'ra' => 'audio/x-realaudio',
'rar' => 'application/octet-stream',
'ram' => 'audio/x-pn-realaudio',
'ras' => 'image/x-cmu-raster',
'rgb' => 'image/x-rgb',
'rm' => 'audio/x-pn-realaudio',
'roff' => 'application/x-troff',
'rpm' => 'audio/x-pn-realaudio-plugin',
'rtf' => 'text/rtf',
'rtx' => 'text/richtext',
'sgm' => 'text/sgml',
'sgml' => 'text/sgml',
'sh' => 'application/x-sh',
'shar' => 'application/x-shar',
'shtml' => 'text/html',
'silo' => 'model/mesh',
'sit' => 'application/x-stuffit',
'skd' => 'application/x-koan',
'skm' => 'application/x-koan',
'skp' => 'application/x-koan',
'skt' => 'application/x-koan',
'smi' => 'application/smil',
'smil' => 'application/smil',
'snd' => 'audio/basic',
'so' => 'application/octet-stream',
'spl' => 'application/x-futuresplash',
'src' => 'application/x-wais-source',
'stc' => 'application/vnd.sun.xml.calc.template',
'std' => 'application/vnd.sun.xml.draw.template',
'sti' => 'application/vnd.sun.xml.impress.template',
'stw' => 'application/vnd.sun.xml.writer.template',
'sv4cpio' => 'application/x-sv4cpio',
'sv4crc' => 'application/x-sv4crc',
'swf' => 'application/x-shockwave-flash',
'sxc' => 'application/vnd.sun.xml.calc',
'sxd' => 'application/vnd.sun.xml.draw',
'sxg' => 'application/vnd.sun.xml.writer.global',
'sxi' => 'application/vnd.sun.xml.impress',
'sxm' => 'application/vnd.sun.xml.math',
'sxw' => 'application/vnd.sun.xml.writer',
't' => 'application/x-troff',
'tar' => 'application/x-tar',
'tcl' => 'application/x-tcl',
'tex' => 'application/x-tex',
'texi' => 'application/x-texinfo',
'texinfo' => 'application/x-texinfo',
'tgz' => 'application/x-gtar',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'tr' => 'application/x-troff',
'tsv' => 'text/tab-separated-values',
'txt' => 'text/plain',
'ustar' => 'application/x-ustar',
'vbs' => 'text/plain', //added by skwashd - for obvious reasons
'vcd' => 'application/x-cdlink',
'vcf' => 'text/x-vcard',
'vcs' => 'text/calendar',
'vfb' => 'text/calendar',
'vrml' => 'model/vrml',
'vsd' => 'application/vnd.visio',
'wav' => 'audio/x-wav',
'wax' => 'audio/x-ms-wax',
'wbmp' => 'image/vnd.wap.wbmp',
'wbxml' => 'application/vnd.wap.wbxml',
'wm' => 'video/x-ms-wm',
'wma' => 'audio/x-ms-wma',
'wmd' => 'application/x-ms-wmd',
'wml' => 'text/vnd.wap.wml',
'wmlc' => 'application/vnd.wap.wmlc',
'wmls' => 'text/vnd.wap.wmlscript',
'wmlsc' => 'application/vnd.wap.wmlscriptc',
'wmv' => 'video/x-ms-wmv',
'wmx' => 'video/x-ms-wmx',
'wmz' => 'application/x-ms-wmz',
'wrl' => 'model/vrml',
'wvx' => 'video/x-ms-wvx',
'xbm' => 'image/x-xbitmap',
'xht' => 'application/xhtml+xml',
'xhtml' => 'application/xhtml+xml',
'xls' => 'application/vnd.ms-excel',
'xlt' => 'application/vnd.ms-excel',
'xml' => 'application/xml',
'xpm' => 'image/x-xpixmap',
'xsl' => 'text/xml',
'xwd' => 'image/x-xwindowdump',
'xyz' => 'chemical/x-xyz',
'z' => 'application/x-compress',
'zip' => 'application/zip',
);
$type = strtolower(substr(strrchr($filename, '.'),1));
if(isset($contentType[$type])) {
$mime = $contentType[$type];
}else {
$mime = 'application/octet-stream';
}
return $mime;
}
}
if(!function_exists('image_type_to_extension')){
function image_type_to_extension($imagetype) {
if(empty($imagetype)) return false;
switch($imagetype) {
case IMAGETYPE_GIF : return '.gif';
case IMAGETYPE_JPEG : return '.jpg';
case IMAGETYPE_PNG : return '.png';
case IMAGETYPE_SWF : return '.swf';
case IMAGETYPE_PSD : return '.psd';
case IMAGETYPE_BMP : return '.bmp';
case IMAGETYPE_TIFF_II : return '.tiff';
case IMAGETYPE_TIFF_MM : return '.tiff';
case IMAGETYPE_JPC : return '.jpc';
case IMAGETYPE_JP2 : return '.jp2';
case IMAGETYPE_JPX : return '.jpf';
case IMAGETYPE_JB2 : return '.jb2';
case IMAGETYPE_SWC : return '.swc';
case IMAGETYPE_IFF : return '.aiff';
case IMAGETYPE_WBMP : return '.wbmp';
case IMAGETYPE_XBM : return '.xbm';
default : return false;
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* IP 地理位置查询类 修改自 CoolCode.CN
* 由于使用UTF8编码 如果使用纯真IP地址库的话 需要对返回结果进行编码转换
* @category ORG
* @package ORG
* @subpackage Net
* @author liu21st <liu21st@gmail.com>
*/
class IpLocation {
/**
* QQWry.Dat文件指针
*
* @var resource
*/
private $fp;
/**
* 第一条IP记录的偏移地址
*
* @var int
*/
private $firstip;
/**
* 最后一条IP记录的偏移地址
*
* @var int
*/
private $lastip;
/**
* IP记录的总条数(不包含版本信息记录)
*
* @var int
*/
private $totalip;
/**
* 构造函数,打开 QQWry.Dat 文件并初始化类中的信息
*
* @param string $filename
* @return IpLocation
*/
public function __construct($filename = "UTFWry.dat") {
$this->fp = 0;
if (($this->fp = fopen(dirname(__FILE__).'/'.$filename, 'rb')) !== false) {
$this->firstip = $this->getlong();
$this->lastip = $this->getlong();
$this->totalip = ($this->lastip - $this->firstip) / 7;
}
}
/**
* 返回读取的长整型数
*
* @access private
* @return int
*/
private function getlong() {
//将读取的little-endian编码的4个字节转化为长整型数
$result = unpack('Vlong', fread($this->fp, 4));
return $result['long'];
}
/**
* 返回读取的3个字节的长整型数
*
* @access private
* @return int
*/
private function getlong3() {
//将读取的little-endian编码的3个字节转化为长整型数
$result = unpack('Vlong', fread($this->fp, 3).chr(0));
return $result['long'];
}
/**
* 返回压缩后可进行比较的IP地址
*
* @access private
* @param string $ip
* @return string
*/
private function packip($ip) {
// 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,
// 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串
return pack('N', intval(ip2long($ip)));
}
/**
* 返回读取的字符串
*
* @access private
* @param string $data
* @return string
*/
private function getstring($data = "") {
$char = fread($this->fp, 1);
while (ord($char) > 0) { // 字符串按照C格式保存,以\0结束
$data .= $char; // 将读取的字符连接到给定字符串之后
$char = fread($this->fp, 1);
}
return $data;
}
/**
* 返回地区信息
*
* @access private
* @return string
*/
private function getarea() {
$byte = fread($this->fp, 1); // 标志字节
switch (ord($byte)) {
case 0: // 没有区域信息
$area = "";
break;
case 1:
case 2: // 标志字节为1或2,表示区域信息被重定向
fseek($this->fp, $this->getlong3());
$area = $this->getstring();
break;
default: // 否则,表示区域信息没有被重定向
$area = $this->getstring($byte);
break;
}
return $area;
}
/**
* 根据所给 IP 地址或域名返回所在地区信息
*
* @access public
* @param string $ip
* @return array
*/
public function getlocation($ip='') {
if (!$this->fp) return null; // 如果数据文件没有被正确打开,则直接返回空
if(empty($ip)) $ip = get_client_ip();
$location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址
$ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址
// 不合法的IP地址会被转化为255.255.255.255
// 对分搜索
$l = 0; // 搜索的下边界
$u = $this->totalip; // 搜索的上边界
$findip = $this->lastip; // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息)
while ($l <= $u) { // 当上边界小于下边界时,查找失败
$i = floor(($l + $u) / 2); // 计算近似中间记录
fseek($this->fp, $this->firstip + $i * 7);
$beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址
// strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式
// 以便用于比较,后面相同。
if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时
$u = $i - 1; // 将搜索的上边界修改为中间记录减一
}
else {
fseek($this->fp, $this->getlong3());
$endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址
if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时
$l = $i + 1; // 将搜索的下边界修改为中间记录加一
}
else { // 用户的IP在中间记录的IP范围内时
$findip = $this->firstip + $i * 7;
break; // 则表示找到结果,退出循环
}
}
}
//获取查找到的IP地理位置信息
fseek($this->fp, $findip);
$location['beginip'] = long2ip($this->getlong()); // 用户IP所在范围的开始地址
$offset = $this->getlong3();
fseek($this->fp, $offset);
$location['endip'] = long2ip($this->getlong()); // 用户IP所在范围的结束地址
$byte = fread($this->fp, 1); // 标志字节
switch (ord($byte)) {
case 1: // 标志字节为1,表示国家和区域信息都被同时重定向
$countryOffset = $this->getlong3(); // 重定向地址
fseek($this->fp, $countryOffset);
$byte = fread($this->fp, 1); // 标志字节
switch (ord($byte)) {
case 2: // 标志字节为2,表示国家信息又被重定向
fseek($this->fp, $this->getlong3());
$location['country'] = $this->getstring();
fseek($this->fp, $countryOffset + 4);
$location['area'] = $this->getarea();
break;
default: // 否则,表示国家信息没有被重定向
$location['country'] = $this->getstring($byte);
$location['area'] = $this->getarea();
break;
}
break;
case 2: // 标志字节为2,表示国家信息被重定向
fseek($this->fp, $this->getlong3());
$location['country'] = $this->getstring();
fseek($this->fp, $offset + 8);
$location['area'] = $this->getarea();
break;
default: // 否则,表示国家信息没有被重定向
$location['country'] = $this->getstring($byte);
$location['area'] = $this->getarea();
break;
}
if (trim($location['country']) == 'CZ88.NET') { // CZ88.NET表示没有有效信息
$location['country'] = '未知';
}
if (trim($location['area']) == 'CZ88.NET') {
$location['area'] = '';
}
return $location;
}
/**
* 析构函数,用于在页面执行结束后自动关闭打开的文件。
*
*/
public function __destruct() {
if ($this->fp) {
fclose($this->fp);
}
$this->fp = 0;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* 文件上传类
* @category ORG
* @package ORG
* @subpackage Net
* @author liu21st <liu21st@gmail.com>
*/
class UploadFile {//类定义开始
private $config = array(
'maxSize' => -1, // 上传文件的最大值
'supportMulti' => true, // 是否支持多文件上传
'allowExts' => array(), // 允许上传的文件后缀 留空不作后缀检查
'allowTypes' => array(), // 允许上传的文件类型 留空不做检查
'thumb' => false, // 使用对上传图片进行缩略图处理
'imageClassPath' => 'ORG.Util.Image', // 图库类包路径
'thumbMaxWidth' => '',// 缩略图最大宽度
'thumbMaxHeight' => '',// 缩略图最大高度
'thumbPrefix' => 'thumb_',// 缩略图前缀
'thumbSuffix' => '',
'thumbPath' => '',// 缩略图保存路径
'thumbFile' => '',// 缩略图文件名
'thumbExt' => '',// 缩略图扩展名
'thumbRemoveOrigin' => false,// 是否移除原图
'thumbType' => 1, // 缩略图生成方式 1 按设置大小截取 0 按原图等比例缩略
'zipImages' => false,// 压缩图片文件上传
'autoSub' => false,// 启用子目录保存文件
'subType' => 'hash',// 子目录创建方式 可以使用hash date custom
'subDir' => '', // 子目录名称 subType为custom方式后有效
'dateFormat' => 'Ymd',
'hashLevel' => 1, // hash的目录层次
'savePath' => '',// 上传文件保存路径
'autoCheck' => true, // 是否自动检查附件
'uploadReplace' => false,// 存在同名是否覆盖
'saveRule' => 'uniqid',// 上传文件命名规则
'hashType' => 'md5_file',// 上传文件Hash规则函数名
);
// 错误信息
private $error = '';
// 上传成功的文件信息
private $uploadFileInfo ;
public function __get($name){
if(isset($this->config[$name])) {
return $this->config[$name];
}
return null;
}
public function __set($name,$value){
if(isset($this->config[$name])) {
$this->config[$name] = $value;
}
}
public function __isset($name){
return isset($this->config[$name]);
}
/**
* 架构函数
* @access public
* @param array $config 上传参数
*/
public function __construct($config=array()) {
if(is_array($config)) {
$this->config = array_merge($this->config,$config);
}
}
/**
* 上传一个文件
* @access public
* @param mixed $name 数据
* @param string $value 数据表名
* @return string
*/
private function save($file) {
$filename = $file['savepath'].$file['savename'];
if(!$this->uploadReplace && is_file($filename)) {
// 不覆盖同名文件
$this->error = '文件已经存在!'.$filename;
return false;
}
// 如果是图像文件 检测文件格式
if( in_array(strtolower($file['extension']),array('gif','jpg','jpeg','bmp','png','swf'))) {
$info = getimagesize($file['tmp_name']);
if(false === $info || ('gif' == strtolower($file['extension']) && empty($info['bits']))){
$this->error = '非法图像文件';
return false;
}
}
if(!move_uploaded_file($file['tmp_name'], $this->autoCharset($filename,'utf-8','gbk'))) {
$this->error = '文件上传保存错误!';
return false;
}
if($this->thumb && in_array(strtolower($file['extension']),array('gif','jpg','jpeg','bmp','png'))) {
$image = getimagesize($filename);
if(false !== $image) {
//是图像文件生成缩略图
$thumbWidth = explode(',',$this->thumbMaxWidth);
$thumbHeight = explode(',',$this->thumbMaxHeight);
$thumbPrefix = explode(',',$this->thumbPrefix);
$thumbSuffix = explode(',',$this->thumbSuffix);
$thumbFile = explode(',',$this->thumbFile);
$thumbPath = $this->thumbPath?$this->thumbPath:dirname($filename).'/';
$thumbExt = $this->thumbExt ? $this->thumbExt : $file['extension']; //自定义缩略图扩展名
// 生成图像缩略图
import($this->imageClassPath);
for($i=0,$len=count($thumbWidth); $i<$len; $i++) {
if(!empty($thumbFile[$i])) {
$thumbname = $thumbFile[$i];
}else{
$prefix = isset($thumbPrefix[$i])?$thumbPrefix[$i]:$thumbPrefix[0];
$suffix = isset($thumbSuffix[$i])?$thumbSuffix[$i]:$thumbSuffix[0];
$thumbname = $prefix.basename($filename,'.'.$file['extension']).$suffix;
}
if(1 == $this->thumbType){
Image::thumb2($filename,$thumbPath.$thumbname.'.'.$thumbExt,'',$thumbWidth[$i],$thumbHeight[$i],true);
}else{
Image::thumb($filename,$thumbPath.$thumbname.'.'.$thumbExt,'',$thumbWidth[$i],$thumbHeight[$i],true);
}
}
if($this->thumbRemoveOrigin) {
// 生成缩略图之后删除原图
unlink($filename);
}
}
}
if($this->zipImags) {
// TODO 对图片压缩包在线解压
}
return true;
}
/**
* 上传所有文件
* @access public
* @param string $savePath 上传文件保存路径
* @return string
*/
public function upload($savePath ='') {
//如果不指定保存文件名,则由系统默认
if(empty($savePath))
$savePath = $this->savePath;
// 检查上传目录
if(!is_dir($savePath)) {
// 检查目录是否编码后的
if(is_dir(base64_decode($savePath))) {
$savePath = base64_decode($savePath);
}else{
// 尝试创建目录
if(!mkdir($savePath)){
$this->error = '上传目录'.$savePath.'不存在';
return false;
}
}
}else {
if(!is_writeable($savePath)) {
$this->error = '上传目录'.$savePath.'不可写';
return false;
}
}
$fileInfo = array();
$isUpload = false;
// 获取上传的文件信息
// 对$_FILES数组信息处理
$files = $this->dealFiles($_FILES);
foreach($files as $key => $file) {
//过滤无效的上传
if(!empty($file['name'])) {
//登记上传文件的扩展信息
if(!isset($file['key'])) $file['key'] = $key;
$file['extension'] = $this->getExt($file['name']);
$file['savepath'] = $savePath;
$file['savename'] = $this->getSaveName($file);
// 自动检查附件
if($this->autoCheck) {
if(!$this->check($file))
return false;
}
//保存上传文件
if(!$this->save($file)) return false;
if(function_exists($this->hashType)) {
$fun = $this->hashType;
$file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk'));
}
//上传成功后保存文件信息,供其他地方调用
unset($file['tmp_name'],$file['error']);
$fileInfo[] = $file;
$isUpload = true;
}
}
if($isUpload) {
$this->uploadFileInfo = $fileInfo;
return true;
}else {
$this->error = '没有选择上传文件';
return false;
}
}
/**
* 上传单个上传字段中的文件 支持多附件
* @access public
* @param array $file 上传文件信息
* @param string $savePath 上传文件保存路径
* @return string
*/
public function uploadOne($file,$savePath=''){
//如果不指定保存文件名,则由系统默认
if(empty($savePath))
$savePath = $this->savePath;
// 检查上传目录
if(!is_dir($savePath)) {
// 尝试创建目录
if(!mkdir($savePath,0777,true)){
$this->error = '上传目录'.$savePath.'不存在';
return false;
}
}else {
if(!is_writeable($savePath)) {
$this->error = '上传目录'.$savePath.'不可写';
return false;
}
}
//过滤无效的上传
if(!empty($file['name'])) {
$fileArray = array();
if(is_array($file['name'])) {
$keys = array_keys($file);
$count = count($file['name']);
for ($i=0; $i<$count; $i++) {
foreach ($keys as $key)
$fileArray[$i][$key] = $file[$key][$i];
}
}else{
$fileArray[] = $file;
}
$info = array();
foreach ($fileArray as $key=>$file){
//登记上传文件的扩展信息
$file['extension'] = $this->getExt($file['name']);
$file['savepath'] = $savePath;
$file['savename'] = $this->getSaveName($file);
// 自动检查附件
if($this->autoCheck) {
if(!$this->check($file))
return false;
}
//保存上传文件
if(!$this->save($file)) return false;
if(function_exists($this->hashType)) {
$fun = $this->hashType;
$file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk'));
}
unset($file['tmp_name'],$file['error']);
$info[] = $file;
}
// 返回上传的文件信息
return $info;
}else {
$this->error = '没有选择上传文件';
return false;
}
}
/**
* 转换上传文件数组变量为正确的方式
* @access private
* @param array $files 上传的文件变量
* @return array
*/
private function dealFiles($files) {
$fileArray = array();
$n = 0;
foreach ($files as $key=>$file){
if(is_array($file['name'])) {
$keys = array_keys($file);
$count = count($file['name']);
for ($i=0; $i<$count; $i++) {
$fileArray[$n]['key'] = $key;
foreach ($keys as $_key){
$fileArray[$n][$_key] = $file[$_key][$i];
}
$n++;
}
}else{
$fileArray[$key] = $file;
}
}
return $fileArray;
}
/**
* 获取错误代码信息
* @access public
* @param string $errorNo 错误号码
* @return void
*/
protected function error($errorNo) {
switch($errorNo) {
case 1:
$this->error = '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值';
break;
case 2:
$this->error = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值';
break;
case 3:
$this->error = '文件只有部分被上传';
break;
case 4:
$this->error = '没有文件被上传';
break;
case 6:
$this->error = '找不到临时文件夹';
break;
case 7:
$this->error = '文件写入失败';
break;
default:
$this->error = '未知上传错误!';
}
return ;
}
/**
* 根据上传文件命名规则取得保存文件名
* @access private
* @param string $filename 数据
* @return string
*/
private function getSaveName($filename) {
$rule = $this->saveRule;
if(empty($rule)) {//没有定义命名规则,则保持文件名不变
$saveName = $filename['name'];
}else {
if(function_exists($rule)) {
//使用函数生成一个唯一文件标识号
$saveName = $rule().".".$filename['extension'];
}else {
//使用给定的文件名作为标识号
$saveName = $rule.".".$filename['extension'];
}
}
if($this->autoSub) {
// 使用子目录保存文件
$filename['savename'] = $saveName;
$saveName = $this->getSubName($filename).$saveName;
}
return $saveName;
}
/**
* 获取子目录的名称
* @access private
* @param array $file 上传的文件信息
* @return string
*/
private function getSubName($file) {
switch($this->subType) {
case 'custom':
$dir = $this->subDir;
break;
case 'date':
$dir = date($this->dateFormat,time()).'/';
break;
case 'hash':
default:
$name = md5($file['savename']);
$dir = '';
for($i=0;$i<$this->hashLevel;$i++) {
$dir .= $name{$i}.'/';
}
break;
}
if(!is_dir($file['savepath'].$dir)) {
mkdir($file['savepath'].$dir,0777,true);
}
return $dir;
}
/**
* 检查上传的文件
* @access private
* @param array $file 文件信息
* @return boolean
*/
private function check($file) {
if($file['error']!== 0) {
//文件上传失败
//捕获错误代码
$this->error($file['error']);
return false;
}
//文件上传成功,进行自定义规则检查
//检查文件大小
if(!$this->checkSize($file['size'])) {
$this->error = '上传文件大小不符!';
return false;
}
//检查文件Mime类型
if(!$this->checkType($file['type'])) {
$this->error = '上传文件MIME类型不允许!';
return false;
}
//检查文件类型
if(!$this->checkExt($file['extension'])) {
$this->error ='上传文件类型不允许';
return false;
}
//检查是否合法上传
if(!$this->checkUpload($file['tmp_name'])) {
$this->error = '非法上传文件!';
return false;
}
return true;
}
// 自动转换字符集 支持数组转换
private function autoCharset($fContents, $from='gbk', $to='utf-8') {
$from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from;
$to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to;
if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) {
//如果编码相同或者非字符串标量则不转换
return $fContents;
}
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($fContents, $to, $from);
} elseif (function_exists('iconv')) {
return iconv($from, $to, $fContents);
} else {
return $fContents;
}
}
/**
* 检查上传的文件类型是否合法
* @access private
* @param string $type 数据
* @return boolean
*/
private function checkType($type) {
if(!empty($this->allowTypes))
return in_array(strtolower($type),$this->allowTypes);
return true;
}
/**
* 检查上传的文件后缀是否合法
* @access private
* @param string $ext 后缀名
* @return boolean
*/
private function checkExt($ext) {
if(!empty($this->allowExts))
return in_array(strtolower($ext),$this->allowExts,true);
return true;
}
/**
* 检查文件大小是否合法
* @access private
* @param integer $size 数据
* @return boolean
*/
private function checkSize($size) {
return !($size > $this->maxSize) || (-1 == $this->maxSize);
}
/**
* 检查文件是否非法提交
* @access private
* @param string $filename 文件名
* @return boolean
*/
private function checkUpload($filename) {
return is_uploaded_file($filename);
}
/**
* 取得上传文件的后缀
* @access private
* @param string $filename 文件名
* @return boolean
*/
private function getExt($filename) {
$pathinfo = pathinfo($filename);
return $pathinfo['extension'];
}
/**
* 取得上传文件的信息
* @access public
* @return array
*/
public function getUploadFileInfo() {
return $this->uploadFileInfo;
}
/**
* 取得最后一次错误信息
* @access public
* @return string
*/
public function getErrorMsg() {
return $this->error;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ArrayList实现类
* @category Think
* @package Think
* @subpackage Util
* @author liu21st <liu21st@gmail.com>
*/
class ArrayList implements IteratorAggregate {
/**
* 集合元素
* @var array
* @access protected
*/
protected $_elements = array();
/**
* 架构函数
* @access public
* @param string $elements 初始化数组元素
*/
public function __construct($elements = array()) {
if (!empty($elements)) {
$this->_elements = $elements;
}
}
/**
* 若要获得迭代因子,通过getIterator方法实现
* @access public
* @return ArrayObject
*/
public function getIterator() {
return new ArrayObject($this->_elements);
}
/**
* 增加元素
* @access public
* @param mixed $element 要添加的元素
* @return boolen
*/
public function add($element) {
return (array_push($this->_elements, $element)) ? true : false;
}
//
public function unshift($element) {
return (array_unshift($this->_elements,$element))?true : false;
}
//
public function pop() {
return array_pop($this->_elements);
}
/**
* 增加元素列表
* @access public
* @param ArrayList $list 元素列表
* @return boolen
*/
public function addAll($list) {
$before = $this->size();
foreach( $list as $element) {
$this->add($element);
}
$after = $this->size();
return ($before < $after);
}
/**
* 清除所有元素
* @access public
*/
public function clear() {
$this->_elements = array();
}
/**
* 是否包含某个元素
* @access public
* @param mixed $element 查找元素
* @return string
*/
public function contains($element) {
return (array_search($element, $this->_elements) !== false );
}
/**
* 根据索引取得元素
* @access public
* @param integer $index 索引
* @return mixed
*/
public function get($index) {
return $this->_elements[$index];
}
/**
* 查找匹配元素,并返回第一个元素所在位置
* 注意 可能存在0的索引位置 因此要用===False来判断查找失败
* @access public
* @param mixed $element 查找元素
* @return integer
*/
public function indexOf($element) {
return array_search($element, $this->_elements);
}
/**
* 判断元素是否为空
* @access public
* @return boolen
*/
public function isEmpty() {
return empty($this->_elements);
}
/**
* 最后一个匹配的元素位置
* @access public
* @param mixed $element 查找元素
* @return integer
*/
public function lastIndexOf($element) {
for ($i = (count($this->_elements) - 1); $i > 0; $i--) {
if ($element == $this->get($i)) { return $i; }
}
}
public function toJson() {
return json_encode($this->_elements);
}
/**
* 根据索引移除元素
* 返回被移除的元素
* @access public
* @param integer $index 索引
* @return mixed
*/
public function remove($index) {
$element = $this->get($index);
if (!is_null($element)) { array_splice($this->_elements, $index, 1); }
return $element;
}
/**
* 移出一定范围的数组列表
* @access public
* @param integer $offset 开始移除位置
* @param integer $length 移除长度
*/
public function removeRange($offset , $length) {
array_splice($this->_elements, $offset , $length);
}
/**
* 移出重复的值
* @access public
*/
public function unique() {
$this->_elements = array_unique($this->_elements);
}
/**
* 取出一定范围的数组列表
* @access public
* @param integer $offset 开始位置
* @param integer $length 长度
*/
public function range($offset,$length=null) {
return array_slice($this->_elements,$offset,$length);
}
/**
* 设置列表元素
* 返回修改之前的值
* @access public
* @param integer $index 索引
* @param mixed $element 元素
* @return mixed
*/
public function set($index, $element) {
$previous = $this->get($index);
$this->_elements[$index] = $element;
return $previous;
}
/**
* 获取列表长度
* @access public
* @return integer
*/
public function size() {
return count($this->_elements);
}
/**
* 转换成数组
* @access public
* @return array
*/
public function toArray() {
return $this->_elements;
}
// 列表排序
public function ksort() {
ksort($this->_elements);
}
// 列表排序
public function asort() {
asort($this->_elements);
}
// 逆向排序
public function rsort() {
rsort($this->_elements);
}
// 自然排序
public function natsort() {
natsort($this->_elements);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2011 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614 <weibo.com/luofei614> 
// +----------------------------------------------------------------------
/**
* 权限认证类
* 功能特性:
* 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。
* $auth=new Auth(); $auth->check('规则名称','用户id')
* 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)
* $auth=new Auth(); $auth->check('规则1,规则2','用户id','and')
* 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or
* 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限)
*
* 4,支持规则表达式。
* 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。
* @category ORG
* @package ORG
* @subpackage Util
* @author luofei614<weibo.com/luofei614>
*/
//数据库
/*
-- ----------------------------
-- think_auth_rule,规则表,
-- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证
-- ----------------------------
DROP TABLE IF EXISTS `think_auth_rule`;
CREATE TABLE `think_auth_rule` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(80) NOT NULL DEFAULT '',
`title` char(20) NOT NULL DEFAULT '',
`status` tinyint(1) NOT NULL DEFAULT '1',
`condition` char(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- think_auth_group 用户组表,
-- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用
-- ----------------------------
DROP TABLE IF EXISTS `think_auth_group`;
CREATE TABLE `think_auth_group` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`title` char(100) NOT NULL DEFAULT '',
`status` tinyint(1) NOT NULL DEFAULT '1',
`rules` char(80) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- think_auth_group_access 用户组明细表
-- uid:用户id,group_id:用户组id
-- ----------------------------
DROP TABLE IF EXISTS `think_auth_group_access`;
CREATE TABLE `think_auth_group_access` (
`uid` mediumint(8) unsigned NOT NULL,
`group_id` mediumint(8) unsigned NOT NULL,
UNIQUE KEY `uid_group_id` (`uid`,`group_id`),
KEY `uid` (`uid`),
KEY `group_id` (`group_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
*/
class Auth{
//默认配置
protected $_config = array(
'AUTH_ON' => true, //认证开关
'AUTH_TYPE' => 1, // 认证方式,1为时时认证;2为登录认证。
'AUTH_GROUP' => 'think_auth_group', //用户组数据表名
'AUTH_GROUP_ACCESS' => 'think_auth_group_access', //用户组明细表
'AUTH_RULE' => 'think_auth_rule', //权限规则表
'AUTH_USER' => 'think_members'//用户信息表
);
public function __construct() {
if (C('AUTH_CONFIG')) {
//可设置配置项 AUTH_CONFIG, 此配置项为数组。
$this->_config = array_merge($this->_config, C('AUTH_CONFIG'));
}
}
//获得权限$name 可以是字符串或数组或逗号分割, uid为 认证的用户id, $or 是否为or关系,为true是, name为数组,只要数组中有一个条件通过则通过,如果为false需要全部条件通过。
public function check($name, $uid, $relation='or') {
if (!$this->_config['AUTH_ON'])
return true;
$authList = $this->getAuthList($uid);
if (is_string($name)) {
if (strpos($name, ',') !== false) {
$name = explode(',', $name);
} else {
$name = array($name);
}
}
$list = array(); //有权限的name
foreach ($authList as $val) {
if (in_array($val, $name))
$list[] = $val;
}
if ($relation=='or' and !empty($list)) {
return true;
}
$diff = array_diff($name, $list);
if ($relation=='and' and empty($diff)) {
return true;
}
return false;
}
//获得用户组,外部也可以调用
public function getGroups($uid) {
static $groups = array();
if (isset($groups[$uid]))
return $groups[$uid];
$user_groups = M()->table($this->_config['AUTH_GROUP_ACCESS'] . ' a')->where("a.uid='$uid' and g.status='1'")->join($this->_config['AUTH_GROUP']." g on a.group_id=g.id")->select();
$groups[$uid]=$user_groups?$user_groups:array();
return $groups[$uid];
}
//获得权限列表
protected function getAuthList($uid) {
static $_authList = array();
if (isset($_authList[$uid])) {
return $_authList[$uid];
}
if(isset($_SESSION['_AUTH_LIST_'.$uid])){
return $_SESSION['_AUTH_LIST_'.$uid];
}
//读取用户所属用户组
$groups = $this->getGroups($uid);
$ids = array();
foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authList[$uid] = array();
return array();
}
//读取用户组所有权限规则
$map=array(
'id'=>array('in',$ids),
'status'=>1
);
$rules = M()->table($this->_config['AUTH_RULE'])->where($map)->select();
//循环规则,判断结果。
$authList = array();
foreach ($rules as $r) {
if (!empty($r['condition'])) {
//条件验证
$user = $this->getUserInfo($uid);
$command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $r['condition']);
//dump($command);//debug
@(eval('$condition=(' . $command . ');'));
if ($condition) {
$authList[] = $r['name'];
}
} else {
//存在就通过
$authList[] = $r['name'];
}
}
$_authList[$uid] = $authList;
if($this->_config['AUTH_TYPE']==2){
//session结果
$_SESSION['_AUTH_LIST_'.$uid]=$authList;
}
return $authList;
}
//获得用户资料,根据自己的情况读取数据库
protected function getUserInfo($uid) {
static $userinfo=array();
if(!isset($userinfo[$uid])){
$userinfo[$uid]=M()->table($this->_config['AUTH_USER'])->find($uid);
}
return $userinfo[$uid];
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
class CodeSwitch {
// 错误信息
static private $error = array();
// 提示信息
static private $info = array();
// 记录错误
static private function error($msg) {
self::$error[] = $msg;
}
// 记录信息
static private function info($info) {
self::$info[] = $info;
}
/**
* 编码转换函数,对整个文件进行编码转换
* 支持以下转换
* GB2312、UTF-8 WITH BOM转换为UTF-8
* UTF-8、UTF-8 WITH BOM转换为GB2312
* @access public
* @param string $filename 文件名
* @param string $out_charset 转换后的文件编码,与iconv使用的参数一致
* @return void
*/
static function DetectAndSwitch($filename,$out_charset) {
$fpr = fopen($filename,"r");
$char1 = fread($fpr,1);
$char2 = fread($fpr,1);
$char3 = fread($fpr,1);
$originEncoding = "";
if($char1==chr(239) && $char2==chr(187) && $char3==chr(191))//UTF-8 WITH BOM
$originEncoding = "UTF-8 WITH BOM";
elseif($char1==chr(255) && $char2==chr(254))//UNICODE LE
{
self::error("不支持从UNICODE LE转换到UTF-8或GB编码");
fclose($fpr);
return;
}elseif($char1==chr(254) && $char2==chr(255)){//UNICODE BE
self::error("不支持从UNICODE BE转换到UTF-8或GB编码");
fclose($fpr);
return;
}else{//没有文件头,可能是GB或UTF-8
if(rewind($fpr)===false){//回到文件开始部分,准备逐字节读取判断编码
self::error($filename."文件指针后移失败");
fclose($fpr);
return;
}
while(!feof($fpr)){
$char = fread($fpr,1);
//对于英文,GB和UTF-8都是单字节的ASCII码小于128的值
if(ord($char)<128)
continue;
//对于汉字GB编码第一个字节是110*****第二个字节是10******(有特例,比如联字)
//UTF-8编码第一个字节是1110****第二个字节是10******第三个字节是10******
//按位与出来结果要跟上面非星号相同,所以应该先判断UTF-8
//因为使用GB的掩码按位与,UTF-8的111得出来的也是110,所以要先判断UTF-8
if((ord($char)&224)==224) {
//第一个字节判断通过
$char = fread($fpr,1);
if((ord($char)&128)==128) {
//第二个字节判断通过
$char = fread($fpr,1);
if((ord($char)&128)==128) {
$originEncoding = "UTF-8";
break;
}
}
}
if((ord($char)&192)==192) {
//第一个字节判断通过
$char = fread($fpr,1);
if((ord($char)&128)==128) {
//第二个字节判断通过
$originEncoding = "GB2312";
break;
}
}
}
}
if(strtoupper($out_charset)==$originEncoding) {
self::info("文件".$filename."转码检查完成,原始文件编码".$originEncoding);
fclose($fpr);
}else {
//文件需要转码
$originContent = "";
if($originEncoding == "UTF-8 WITH BOM") {
//跳过三个字节,把后面的内容复制一遍得到utf-8的内容
fseek($fpr,3);
$originContent = fread($fpr,filesize($filename)-3);
fclose($fpr);
}elseif(rewind($fpr)!=false){//不管是UTF-8还是GB2312,回到文件开始部分,读取内容
$originContent = fread($fpr,filesize($filename));
fclose($fpr);
}else{
self::error("文件编码不正确或指针后移失败");
fclose($fpr);
return;
}
//转码并保存文件
$content = iconv(str_replace(" WITH BOM","",$originEncoding),strtoupper($out_charset),$originContent);
$fpw = fopen($filename,"w");
fwrite($fpw,$content);
fclose($fpw);
if($originEncoding!="")
self::info("对文件".$filename."转码完成,原始文件编码".$originEncoding.",转换后文件编码".strtoupper($out_charset));
elseif($originEncoding=="")
self::info("文件".$filename."中没有出现中文,但是可以断定不是带BOM的UTF-8编码,没有进行编码转换,不影响使用");
}
}
/**
* 目录遍历函数
* @access public
* @param string $path 要遍历的目录名
* @param string $mode 遍历模式,一般取FILES,这样只返回带路径的文件名
* @param array $file_types 文件后缀过滤数组
* @param int $maxdepth 遍历深度,-1表示遍历到最底层
* @return void
*/
static function searchdir($path,$mode = "FULL",$file_types = array(".html",".php"),$maxdepth = -1,$d = 0) {
if(substr($path,strlen($path)-1) != '/')
$path .= '/';
$dirlist = array();
if($mode != "FILES")
$dirlist[] = $path;
if($handle = @opendir($path)) {
while(false !== ($file = readdir($handle)))
{
if($file != '.' && $file != '..')
{
$file = $path.$file ;
if(!is_dir($file))
{
if($mode != "DIRS")
{
$extension = "";
$extpos = strrpos($file, '.');
if($extpos!==false)
$extension = substr($file,$extpos,strlen($file)-$extpos);
$extension=strtolower($extension);
if(in_array($extension, $file_types))
$dirlist[] = $file;
}
}
elseif($d >= 0 && ($d < $maxdepth || $maxdepth < 0))
{
$result = self::searchdir($file.'/',$mode,$file_types,$maxdepth,$d + 1) ;
$dirlist = array_merge($dirlist,$result);
}
}
}
closedir ( $handle ) ;
}
if($d == 0)
natcasesort($dirlist);
return($dirlist) ;
}
/**
* 对整个项目目录中的PHP和HTML文件行进编码转换
* @access public
* @param string $app 要遍历的项目路径
* @param string $mode 遍历模式,一般取FILES,这样只返回带路径的文件名
* @param array $file_types 文件后缀过滤数组
* @return void
*/
static function CodingSwitch($app = "./",$charset='UTF-8',$mode = "FILES",$file_types = array(".html",".php")) {
self::info("注意: 程序使用的文件编码检测算法可能对某些特殊字符不适用");
$filearr = self::searchdir($app,$mode,$file_types);
foreach($filearr as $file)
self::DetectAndSwitch($file,$charset);
}
static public function getError() {
return self::$error;
}
static public function getInfo() {
return self::$info;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* 日期时间操作类
* @category ORG
* @package ORG
* @subpackage Date
* @author liu21st <liu21st@gmail.com>
* @version $Id: Date.class.php 2662 2012-01-26 06:32:50Z liu21st $
*/
class Date {
/**
* 日期的时间戳
* @var integer
* @access protected
*/
protected $date;
/**
* 时区
* @var integer
* @access protected
*/
protected $timezone;
/**
* 年
* @var integer
* @access protected
*/
protected $year;
/**
* 月
* @var integer
* @access protected
*/
protected $month;
/**
* 日
* @var integer
* @access protected
*/
protected $day;
/**
* 时
* @var integer
* @access protected
*/
protected $hour;
/**
* 分
* @var integer
* @access protected
*/
protected $minute;
/**
* 秒
* @var integer
* @access protected
*/
protected $second;
/**
* 星期的数字表示
* @var integer
* @access protected
*/
protected $weekday;
/**
* 星期的完整表示
* @var string
* @access protected
*/
protected $cWeekday;
/**
* 一年中的天数 0-365
* @var integer
* @access protected
*/
protected $yDay;
/**
* 月份的完整表示
* @var string
* @access protected
*/
protected $cMonth;
/**
* 日期CDATE表示
* @var string
* @access protected
*/
protected $CDATE;
/**
* 日期的YMD表示
* @var string
* @access protected
*/
protected $YMD;
/**
* 时间的输出表示
* @var string
* @access protected
*/
protected $CTIME;
// 星期的输出
protected $Week = array("日","一","二","三","四","五","六");
/**
* 架构函数
* 创建一个Date对象
* @param mixed $date 日期
* @static
* @access public
*/
public function __construct($date='') {
//分析日期
$this->date = $this->parse($date);
$this->setDate($this->date);
}
/**
* 日期分析
* 返回时间戳
* @static
* @access public
* @param mixed $date 日期
* @return string
*/
public function parse($date) {
if (is_string($date)) {
if (($date == "") || strtotime($date) == -1) {
//为空默认取得当前时间戳
$tmpdate = time();
} else {
//把字符串转换成UNIX时间戳
$tmpdate = strtotime($date);
}
} elseif (is_null($date)) {
//为空默认取得当前时间戳
$tmpdate = time();
} elseif (is_numeric($date)) {
//数字格式直接转换为时间戳
$tmpdate = $date;
} else {
if (get_class($date) == "Date") {
//如果是Date对象
$tmpdate = $date->date;
} else {
//默认取当前时间戳
$tmpdate = time();
}
}
return $tmpdate;
}
/**
* 验证日期数据是否有效
* @access public
* @param mixed $date 日期数据
* @return string
*/
public function valid($date) {
}
/**
* 日期参数设置
* @static
* @access public
* @param integer $date 日期时间戳
* @return void
*/
public function setDate($date) {
$dateArray = getdate($date);
$this->date = $dateArray[0]; //时间戳
$this->second = $dateArray["seconds"]; //秒
$this->minute = $dateArray["minutes"]; //分
$this->hour = $dateArray["hours"]; //时
$this->day = $dateArray["mday"]; //日
$this->month = $dateArray["mon"]; //月
$this->year = $dateArray["year"]; //年
$this->weekday = $dateArray["wday"]; //星期 0~6
$this->cWeekday = '星期'.$this->Week[$this->weekday];//$dateArray["weekday"]; //星期完整表示
$this->yDay = $dateArray["yday"]; //一年中的天数 0-365
$this->cMonth = $dateArray["month"]; //月份的完整表示
$this->CDATE = $this->format("%Y-%m-%d");//日期表示
$this->YMD = $this->format("%Y%m%d"); //简单日期
$this->CTIME = $this->format("%H:%M:%S");//时间表示
return ;
}
/**
* 日期格式化
* 默认返回 1970-01-01 11:30:45 格式
* @access public
* @param string $format 格式化参数
* @return string
*/
public function format($format = "%Y-%m-%d %H:%M:%S") {
return strftime($format, $this->date);
}
/**
* 是否为闰年
* @static
* @access public
* @return string
*/
public function isLeapYear($year='') {
if(empty($year)) {
$year = $this->year;
}
return ((($year % 4) == 0) && (($year % 100) != 0) || (($year % 400) == 0));
}
/**
* 计算日期差
*
* w - weeks
* d - days
* h - hours
* m - minutes
* s - seconds
* @static
* @access public
* @param mixed $date 要比较的日期
* @param string $elaps 比较跨度
* @return integer
*/
public function dateDiff($date, $elaps = "d") {
$__DAYS_PER_WEEK__ = (7);
$__DAYS_PER_MONTH__ = (30);
$__DAYS_PER_YEAR__ = (365);
$__HOURS_IN_A_DAY__ = (24);
$__MINUTES_IN_A_DAY__ = (1440);
$__SECONDS_IN_A_DAY__ = (86400);
//计算天数差
$__DAYSELAPS = ($this->parse($date) - $this->date) / $__SECONDS_IN_A_DAY__ ;
switch ($elaps) {
case "y"://转换成年
$__DAYSELAPS = $__DAYSELAPS / $__DAYS_PER_YEAR__;
break;
case "M"://转换成月
$__DAYSELAPS = $__DAYSELAPS / $__DAYS_PER_MONTH__;
break;
case "w"://转换成星期
$__DAYSELAPS = $__DAYSELAPS / $__DAYS_PER_WEEK__;
break;
case "h"://转换成小时
$__DAYSELAPS = $__DAYSELAPS * $__HOURS_IN_A_DAY__;
break;
case "m"://转换成分钟
$__DAYSELAPS = $__DAYSELAPS * $__MINUTES_IN_A_DAY__;
break;
case "s"://转换成秒
$__DAYSELAPS = $__DAYSELAPS * $__SECONDS_IN_A_DAY__;
break;
}
return $__DAYSELAPS;
}
/**
* 人性化的计算日期差
* @static
* @access public
* @param mixed $time 要比较的时间
* @param mixed $precision 返回的精度
* @return string
*/
public function timeDiff( $time ,$precision=false) {
if(!is_numeric($precision) && !is_bool($precision)) {
static $_diff = array('y'=>'年','M'=>'个月','d'=>'天','w'=>'周','s'=>'秒','h'=>'小时','m'=>'分钟');
return ceil($this->dateDiff($time,$precision)).$_diff[$precision].'前';
}
$diff = abs($this->parse($time) - $this->date);
static $chunks = array(array(31536000,'年'),array(2592000,'个月'),array(604800,'周'),array(86400,'天'),array(3600 ,'小时'),array(60,'分钟'),array(1,'秒'));
$count =0;
$since = '';
for($i=0;$i<count($chunks);$i++) {
if($diff>=$chunks[$i][0]) {
$num = floor($diff/$chunks[$i][0]);
$since .= sprintf('%d'.$chunks[$i][1],$num);
$diff = (int)($diff-$chunks[$i][0]*$num);
$count++;
if(!$precision || $count>=$precision) {
break;
}
}
}
return $since.'前';
}
/**
* 返回周的某一天 返回Date对象
* @access public
* @return Date
*/
public function getDayOfWeek($n){
$week = array(0=>'sunday',1=>'monday',2=>'tuesday',3=>'wednesday',4=>'thursday',5=>'friday',6=>'saturday');
return (new Date($week[$n]));
}
/**
* 计算周的第一天 返回Date对象
* @access public
* @return Date
*/
public function firstDayOfWeek() {
return $this->getDayOfWeek(1);
}
/**
* 计算月份的第一天 返回Date对象
* @access public
* @return Date
*/
public function firstDayOfMonth() {
return (new Date(mktime(0, 0, 0,$this->month,1,$this->year )));
}
/**
* 计算年份的第一天 返回Date对象
* @access public
* @return Date
*/
public function firstDayOfYear() {
return (new Date(mktime(0, 0, 0, 1, 1, $this->year)));
}
/**
* 计算周的最后一天 返回Date对象
* @access public
* @return Date
*/
public function lastDayOfWeek() {
return $this->getDayOfWeek(0);
}
/**
* 计算月份的最后一天 返回Date对象
* @access public
* @return Date
*/
public function lastDayOfMonth() {
return (new Date(mktime(0, 0, 0, $this->month + 1, 0, $this->year )));
}
/**
* 计算年份的最后一天 返回Date对象
* @access public
* @return Date
*/
public function lastDayOfYear() {
return (new Date(mktime(0, 0, 0, 1, 0, $this->year + 1)));
}
/**
* 计算月份的最大天数
* @access public
* @return integer
*/
public function maxDayOfMonth() {
$result = $this->dateDiff(strtotime($this->dateAdd(1,'m')),'d');
return $result;
}
/**
* 取得指定间隔日期
*
* yyyy - 年
* q - 季度
* m - 月
* y - day of year
* d - 日
* w - 周
* ww - week of year
* h - 小时
* n - 分钟
* s - 秒
* @access public
* @param integer $number 间隔数目
* @param string $interval 比较类型
* @return Date
*/
public function dateAdd($number = 0, $interval = "d") {
$hours = $this->hour;
$minutes = $this->minute;
$seconds = $this->second;
$month = $this->month;
$day = $this->day;
$year = $this->year;
switch ($interval) {
case "yyyy":
//---Add $number to year
$year += $number;
break;
case "q":
//---Add $number to quarter
$month += ($number*3);
break;
case "m":
//---Add $number to month
$month += $number;
break;
case "y":
case "d":
case "w":
//---Add $number to day of year, day, day of week
$day += $number;
break;
case "ww":
//---Add $number to week
$day += ($number*7);
break;
case "h":
//---Add $number to hours
$hours += $number;
break;
case "n":
//---Add $number to minutes
$minutes += $number;
break;
case "s":
//---Add $number to seconds
$seconds += $number;
break;
}
return (new Date(mktime($hours,
$minutes,
$seconds,
$month,
$day,
$year)));
}
/**
* 日期数字转中文
* 用于日和月、周
* @static
* @access public
* @param integer $number 日期数字
* @return string
*/
public function numberToCh($number) {
$number = intval($number);
$array = array('一','二','三','四','五','六','七','八','九','十');
$str = '';
if($number ==0) { $str .= "十" ;}
if($number < 10){
$str .= $array[$number-1] ;
}
elseif($number < 20 ){
$str .= "十".$array[$number-11];
}
elseif($number < 30 ){
$str .= "二十".$array[$number-21];
}
else{
$str .= "三十".$array[$number-31];
}
return $str;
}
/**
* 年份数字转中文
* @static
* @access public
* @param integer $yearStr 年份数字
* @param boolean $flag 是否显示公元
* @return string
*/
public function yearToCh( $yearStr ,$flag=false ) {
$array = array('零','一','二','三','四','五','六','七','八','九');
$str = $flag? '公元' : '';
for($i=0;$i<4;$i++){
$str .= $array[substr($yearStr,$i,1)];
}
return $str;
}
/**
* 判断日期 所属 干支 生肖 星座
* type 参数:XZ 星座 GZ 干支 SX 生肖
*
* @static
* @access public
* @param string $type 获取信息类型
* @return string
*/
public function magicInfo($type) {
$result = '';
$m = $this->month;
$y = $this->year;
$d = $this->day;
switch ($type) {
case 'XZ'://星座
$XZDict = array('摩羯','宝瓶','双鱼','白羊','金牛','双子','巨蟹','狮子','处女','天秤','天蝎','射手');
$Zone = array(1222,122,222,321,421,522,622,722,822,922,1022,1122,1222);
if((100*$m+$d)>=$Zone[0]||(100*$m+$d)<$Zone[1])
$i=0;
else
for($i=1;$i<12;$i++){
if((100*$m+$d)>=$Zone[$i]&&(100*$m+$d)<$Zone[$i+1])
break;
}
$result = $XZDict[$i].'座';
break;
case 'GZ'://干支
$GZDict = array(
array('甲','乙','丙','丁','戊','己','庚','辛','壬','癸'),
array('子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥')
);
$i= $y -1900+36 ;
$result = $GZDict[0][$i%10].$GZDict[1][$i%12];
break;
case 'SX'://生肖
$SXDict = array('鼠','牛','虎','兔','龙','蛇','马','羊','猴','鸡','狗','猪');
$result = $SXDict[($y-4)%12];
break;
}
return $result;
}
public function __toString() {
return $this->format();
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* 系统调试类
* @category Think
* @package Think
* @subpackage Util
* @author liu21st <liu21st@gmail.com>
*/
class Debug {
static private $marker = array();
/**
* 标记调试位
* @access public
* @param string $name 要标记的位置名称
* @return void
*/
static public function mark($name) {
self::$marker['time'][$name] = microtime(TRUE);
if(MEMORY_LIMIT_ON) {
self::$marker['mem'][$name] = memory_get_usage();
self::$marker['peak'][$name] = function_exists('memory_get_peak_usage')?memory_get_peak_usage(): self::$marker['mem'][$name];
}
}
/**
* 区间使用时间查看
* @access public
* @param string $start 开始标记的名称
* @param string $end 结束标记的名称
* @param integer $decimals 时间的小数位
* @return integer
*/
static public function useTime($start,$end,$decimals = 6) {
if ( ! isset(self::$marker['time'][$start]))
return '';
if ( ! isset(self::$marker['time'][$end]))
self::$marker['time'][$end] = microtime(TRUE);
return number_format(self::$marker['time'][$end] - self::$marker['time'][$start], $decimals);
}
/**
* 区间使用内存查看
* @access public
* @param string $start 开始标记的名称
* @param string $end 结束标记的名称
* @return integer
*/
static public function useMemory($start,$end) {
if(!MEMORY_LIMIT_ON)
return '';
if ( ! isset(self::$marker['mem'][$start]))
return '';
if ( ! isset(self::$marker['mem'][$end]))
self::$marker['mem'][$end] = memory_get_usage();
return number_format((self::$marker['mem'][$end] - self::$marker['mem'][$start])/1024);
}
/**
* 区间使用内存峰值查看
* @access public
* @param string $start 开始标记的名称
* @param string $end 结束标记的名称
* @return integer
*/
static function getMemPeak($start,$end) {
if(!MEMORY_LIMIT_ON)
return '';
if ( ! isset(self::$marker['peak'][$start]))
return '';
if ( ! isset(self::$marker['peak'][$end]))
self::$marker['peak'][$end] = function_exists('memory_get_peak_usage')?memory_get_peak_usage(): memory_get_usage();
return number_format(max(self::$marker['peak'][$start],self::$marker['peak'][$end])/1024);
}
}
<?php
/* 海龙挖掘机 2.0正式版
* 正文提取,分析,可自动判断编码,自动转码
* 原理:根据代码块加权的原理,首先将HTML分成若干个小块,然后对每个小块进行评分。
* 取分数在3分以上的代码块中的内容返回
* 加分项 1 含有标点符号
* 2 含有<p>标签
* 3 含有<br>标签
* 减分项 1 含有li标签
* 2 不包含任何标点符号
* 3 含有关键词javascript
* 4 不包含任何中文的,直接删除
* 5 有<li><a这样标签
* 实例:
* $he = new HtmlExtractor();
* $str = $he->text($html);
* 其中$html是某个网页的HTML代码,$str是返回的正文,正文编码是utf-8的
*/
class HtmlExtractor {
/*
* 取得汉字的个数(目前不太精确)
*/
function chineseCount($str){
$count = preg_match_all("/[\xB0-\xF7][\xA1-\xFE]/",$str,$ff);
return $count;
}
/*
* 判断一段文字是否是UTF-8,如果不是,那么要转成UTF-8
*/
function getutf8($str){
if(!$this->is_utf8(substr(strip_tags($str),0,500))){
$str = $this->auto_charset($str,"gbk","utf-8");
}
return $str;
}
function is_utf8($string)
{
if(preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$string) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$string) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$string) == true){
return true;
}else{
return false;
}
}
/*
* 自动转换字符集,支持数组和字符串
*/
function auto_charset($fContents,$from,$to){
$from = strtoupper($from)=='UTF8'? 'utf-8':$from;
$to = strtoupper($to)=='UTF8'? 'utf-8':$to;
if( strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents)) ){
//如果编码相同或者非字符串标量则不转换
return $fContents;
}
if(is_string($fContents) ) {
if(function_exists('mb_convert_encoding')){
return mb_convert_encoding ($fContents, $to, $from);
}elseif(function_exists('iconv')){
return iconv($from,$to,$fContents);
}else{
return $fContents;
}
}
elseif(is_array($fContents)){
foreach ( $fContents as $key => $val ) {
$_key = $this->auto_charset($key,$from,$to);
$fContents[$_key] = $this->auto_charset($val,$from,$to);
if($key != $_key )
unset($fContents[$key]);
}
return $fContents;
}
else{
return $fContents;
}
}
/*
* 进行正文提取动作
*/
function text($str){
$str = $this->clear($str);
$str = $this->getutf8($str);
$divList = $this->divList($str);
$content = array();
foreach($divList[0] as $k=>$v){
//首先判断,如果这个内容块的汉字数量站总数量的一半还多,那么就直接保留
//还要判断,是不是一个A标签把整个内容都扩上
if($this->chineseCount($v)/(strlen($v)/3) >= 0.4 && $this->checkHref($v)){
array_push($content,strip_tags($v,"<p><br>"));
}else if($this->makeScore($v) >= 3){
//然后根据分数判断,如果大于3分的,保留
array_push($content,strip_tags($v,"<p><br>"));
}else{
//这些就是排除的内容了
}
}
return implode("",$content);
}
/*
* 判断是不是一个A标签把整个内容都扩上
* 判断方法:把A标签和它的内容都去掉后,看是否还含有中文
*/
private function checkHref($str){
if(!preg_match("'<a[^>]*?>(.*)</a>'si",$str)){
//如果不包含A标签,那不用管了,99%是正文
return true;
}
$clear_str = preg_replace("'<a[^>]*?>(.*)</a>'si","",$str);
if($this->chineseCount($clear_str)){
return true;
}else{
return false;
}
}
function makeScore($str){
$score = 0;
//标点分数
$score += $this->score1($str);
//判断含有P标签
$score += $this->score2($str);
//判断是否含有br标签
$score += $this->score3($str);
//判断是否含有li标签
$score -= $this->score4($str);
//判断是否不包含任何标点符号
$score -= $this->score5($str);
//判断javascript关键字
$score -= $this->score6($str);
//判断<li><a这样的标签
$score -= $this->score7($str);
return $score;
}
/*
* 判断是否有标点符号
*/
private function score1($str){
//取得标点符号的个数
$count = preg_match_all("/(,|。|!|(|)|“|”|;|《|》|、)/si",$str,$out);
if($count){
return $count * 2;
}else{
return 0;
}
}
/*
* 判断是否含有P标签
*/
private function score2($str){
$count = preg_match_all("'<p[^>]*?>.*?</p>'si",$str,$out);
return $count * 2;
}
/*
* 判断是否含有BR标签
*/
private function score3($str){
$count = preg_match_all("'<br/>'si",$str,$out) + preg_match_all("'<br>'si",$str,$out);
return $count * 2;
}
/*
* 判断是否含有li标签
*/
private function score4($str){
//有多少,减多少分 * 2
$count = preg_match_all("'<li[^>]*?>.*?</li>'si",$str,$out);
return $count * 2;
}
/*
* 判断是否不包含任何标点符号
*/
private function score5($str){
if(!preg_match_all("/(,|。|!|(|)|“|”|;|《|》|、|【|】)/si",$str,$out)){
return 2;
}else{
return 0;
}
}
/*
* 判断是否包含javascript关键字,有几个,减几分
*/
private function score6($str){
$count = preg_match_all("'javascript'si",$str,$out);
return $count;
}
/*
* 判断<li><a这样的标签,有几个,减几分
*/
private function score7($str){
$count = preg_match_all("'<li[^>]*?>.*?<a'si",$str,$out);
return $count * 2;
}
/*
* 去噪
*/
private function clear($str){
$str = preg_replace("'<script[^>]*?>.*?</script>'si","",$str);
$str = preg_replace("'<style[^>]*?>.*?</style>'si","",$str);
$str = preg_replace("'<!--.*?-->'si","",$str);
return $str;
}
/*
* 取得内容块
*/
private function divList($str){
preg_match_all("'<[^a][^>]*?>.*?</[^>]*?>'si",$str,$divlist);
return $divlist;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* 图像操作类库
* @category ORG
* @package ORG
* @subpackage Util
* @author liu21st <liu21st@gmail.com>
*/
class Image {
/**
* 取得图像信息
* @static
* @access public
* @param string $image 图像文件名
* @return mixed
*/
static function getImageInfo($img) {
$imageInfo = getimagesize($img);
if ($imageInfo !== false) {
$imageType = strtolower(substr(image_type_to_extension($imageInfo[2]), 1));
$imageSize = filesize($img);
$info = array(
"width" => $imageInfo[0],
"height" => $imageInfo[1],
"type" => $imageType,
"size" => $imageSize,
"mime" => $imageInfo['mime']
);
return $info;
} else {
return false;
}
}
/**
* 为图片添加水印
* @static public
* @param string $source 原文件名
* @param string $water 水印图片
* @param string $$savename 添加水印后的图片名
* @param string $alpha 水印的透明度
* @return void
*/
static public function water($source, $water, $savename=null, $alpha=80) {
//检查文件是否存在
if (!file_exists($source) || !file_exists($water))
return false;
//图片信息
$sInfo = self::getImageInfo($source);
$wInfo = self::getImageInfo($water);
//如果图片小于水印图片,不生成图片
if ($sInfo["width"] < $wInfo["width"] || $sInfo['height'] < $wInfo['height'])
return false;
//建立图像
$sCreateFun = "imagecreatefrom" . $sInfo['type'];
$sImage = $sCreateFun($source);
$wCreateFun = "imagecreatefrom" . $wInfo['type'];
$wImage = $wCreateFun($water);
//设定图像的混色模式
imagealphablending($wImage, true);
//图像位置,默认为右下角右对齐
$posY = $sInfo["height"] - $wInfo["height"];
$posX = $sInfo["width"] - $wInfo["width"];
//生成混合图像
imagecopymerge($sImage, $wImage, $posX, $posY, 0, 0, $wInfo['width'], $wInfo['height'], $alpha);
//输出图像
$ImageFun = 'Image' . $sInfo['type'];
//如果没有给出保存文件名,默认为原图像名
if (!$savename) {
$savename = $source;
@unlink($source);
}
//保存图像
$ImageFun($sImage, $savename);
imagedestroy($sImage);
}
function showImg($imgFile, $text='', $x='10', $y='10', $alpha='50') {
//获取图像文件信息
//2007/6/26 增加图片水印输出,$text为图片的完整路径即可
$info = Image::getImageInfo($imgFile);
if ($info !== false) {
$createFun = str_replace('/', 'createfrom', $info['mime']);
$im = $createFun($imgFile);
if ($im) {
$ImageFun = str_replace('/', '', $info['mime']);
//水印开始
if (!empty($text)) {
$tc = imagecolorallocate($im, 0, 0, 0);
if (is_file($text) && file_exists($text)) {//判断$text是否是图片路径
// 取得水印信息
$textInfo = Image::getImageInfo($text);
$createFun2 = str_replace('/', 'createfrom', $textInfo['mime']);
$waterMark = $createFun2($text);
//$waterMark=imagecolorallocatealpha($text,255,255,0,50);
$imgW = $info["width"];
$imgH = $info["width"] * $textInfo["height"] / $textInfo["width"];
//$y = ($info["height"]-$textInfo["height"])/2;
//设置水印的显示位置和透明度支持各种图片格式
imagecopymerge($im, $waterMark, $x, $y, 0, 0, $textInfo['width'], $textInfo['height'], $alpha);
} else {
imagestring($im, 80, $x, $y, $text, $tc);
}
//ImageDestroy($tc);
}
//水印结束
if ($info['type'] == 'png' || $info['type'] == 'gif') {
imagealphablending($im, FALSE); //取消默认的混色模式
imagesavealpha($im, TRUE); //设定保存完整的 alpha 通道信息
}
Header("Content-type: " . $info['mime']);
$ImageFun($im);
@ImageDestroy($im);
return;
}
//保存图像
$ImageFun($sImage, $savename);
imagedestroy($sImage);
//获取或者创建图像文件失败则生成空白PNG图片
$im = imagecreatetruecolor(80, 30);
$bgc = imagecolorallocate($im, 255, 255, 255);
$tc = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
imagestring($im, 4, 5, 5, "no pic", $tc);
Image::output($im);
return;
}
}
/**
* 生成缩略图
* @static
* @access public
* @param string $image 原图
* @param string $type 图像格式
* @param string $thumbname 缩略图文件名
* @param string $maxWidth 宽度
* @param string $maxHeight 高度
* @param string $position 缩略图保存目录
* @param boolean $interlace 启用隔行扫描
* @return void
*/
static function thumb($image, $thumbname, $type='', $maxWidth=200, $maxHeight=50, $interlace=true) {
// 获取原图信息
$info = Image::getImageInfo($image);
if ($info !== false) {
$srcWidth = $info['width'];
$srcHeight = $info['height'];
$type = empty($type) ? $info['type'] : $type;
$type = strtolower($type);
$interlace = $interlace ? 1 : 0;
unset($info);
$scale = min($maxWidth / $srcWidth, $maxHeight / $srcHeight); // 计算缩放比例
if ($scale >= 1) {
// 超过原图大小不再缩略
$width = $srcWidth;
$height = $srcHeight;
} else {
// 缩略图尺寸
$width = (int) ($srcWidth * $scale);
$height = (int) ($srcHeight * $scale);
}
// 载入原图
$createFun = 'ImageCreateFrom' . ($type == 'jpg' ? 'jpeg' : $type);
if(!function_exists($createFun)) {
return false;
}
$srcImg = $createFun($image);
//创建缩略图
if ($type != 'gif' && function_exists('imagecreatetruecolor'))
$thumbImg = imagecreatetruecolor($width, $height);
else
$thumbImg = imagecreate($width, $height);
//png和gif的透明处理 by luofei614
if('png'==$type){
imagealphablending($thumbImg, false);//取消默认的混色模式(为解决阴影为绿色的问题)
imagesavealpha($thumbImg,true);//设定保存完整的 alpha 通道信息(为解决阴影为绿色的问题)
}elseif('gif'==$type){
$trnprt_indx = imagecolortransparent($srcImg);
if ($trnprt_indx >= 0) {
//its transparent
$trnprt_color = imagecolorsforindex($srcImg , $trnprt_indx);
$trnprt_indx = imagecolorallocate($thumbImg, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
imagefill($thumbImg, 0, 0, $trnprt_indx);
imagecolortransparent($thumbImg, $trnprt_indx);
}
}
// 复制图片
if (function_exists("ImageCopyResampled"))
imagecopyresampled($thumbImg, $srcImg, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight);
else
imagecopyresized($thumbImg, $srcImg, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight);
// 对jpeg图形设置隔行扫描
if ('jpg' == $type || 'jpeg' == $type)
imageinterlace($thumbImg, $interlace);
// 生成图片
$imageFun = 'image' . ($type == 'jpg' ? 'jpeg' : $type);
$imageFun($thumbImg, $thumbname);
imagedestroy($thumbImg);
imagedestroy($srcImg);
return $thumbname;
}
return false;
}
/**
* 生成特定尺寸缩略图 解决原版缩略图不能满足特定尺寸的问题 PS:会裁掉图片不符合缩略图比例的部分
* @static
* @access public
* @param string $image 原图
* @param string $type 图像格式
* @param string $thumbname 缩略图文件名
* @param string $maxWidth 宽度
* @param string $maxHeight 高度
* @param boolean $interlace 启用隔行扫描
* @return void
*/
static function thumb2($image, $thumbname, $type='', $maxWidth=200, $maxHeight=50, $interlace=true) {
// 获取原图信息
$info = Image::getImageInfo($image);
if ($info !== false) {
$srcWidth = $info['width'];
$srcHeight = $info['height'];
$type = empty($type) ? $info['type'] : $type;
$type = strtolower($type);
$interlace = $interlace ? 1 : 0;
unset($info);
$scale = max($maxWidth / $srcWidth, $maxHeight / $srcHeight); // 计算缩放比例
//判断原图和缩略图比例 如原图宽于缩略图则裁掉两边 反之..
if($maxWidth / $srcWidth > $maxHeight / $srcHeight){
//高于
$srcX = 0;
$srcY = ($srcHeight - $maxHeight / $scale) / 2 ;
$cutWidth = $srcWidth;
$cutHeight = $maxHeight / $scale;
}else{
//宽于
$srcX = ($srcWidth - $maxWidth / $scale) / 2;
$srcY = 0;
$cutWidth = $maxWidth / $scale;
$cutHeight = $srcHeight;
}
// 载入原图
$createFun = 'ImageCreateFrom' . ($type == 'jpg' ? 'jpeg' : $type);
$srcImg = $createFun($image);
//创建缩略图
if ($type != 'gif' && function_exists('imagecreatetruecolor'))
$thumbImg = imagecreatetruecolor($maxWidth, $maxHeight);
else
$thumbImg = imagecreate($maxWidth, $maxHeight);
// 复制图片
if (function_exists("ImageCopyResampled"))
imagecopyresampled($thumbImg, $srcImg, 0, 0, $srcX, $srcY, $maxWidth, $maxHeight, $cutWidth, $cutHeight);
else
imagecopyresized($thumbImg, $srcImg, 0, 0, $srcX, $srcY, $maxWidth, $maxHeight, $cutWidth, $cutHeight);
if ('gif' == $type || 'png' == $type) {
//imagealphablending($thumbImg, false);//取消默认的混色模式
//imagesavealpha($thumbImg,true);//设定保存完整的 alpha 通道信息
$background_color = imagecolorallocate($thumbImg, 0, 255, 0); // 指派一个绿色
imagecolortransparent($thumbImg, $background_color); // 设置为透明色,若注释掉该行则输出绿色的图
}
// 对jpeg图形设置隔行扫描
if ('jpg' == $type || 'jpeg' == $type)
imageinterlace($thumbImg, $interlace);
// 生成图片
$imageFun = 'image' . ($type == 'jpg' ? 'jpeg' : $type);
$imageFun($thumbImg, $thumbname);
imagedestroy($thumbImg);
imagedestroy($srcImg);
return $thumbname;
}
return false;
}
/**
* 根据给定的字符串生成图像
* @static
* @access public
* @param string $string 字符串
* @param string $size 图像大小 width,height 或者 array(width,height)
* @param string $font 字体信息 fontface,fontsize 或者 array(fontface,fontsize)
* @param string $type 图像格式 默认PNG
* @param integer $disturb 是否干扰 1 点干扰 2 线干扰 3 复合干扰 0 无干扰
* @param bool $border 是否加边框 array(color)
* @return string
*/
static function buildString($string, $rgb=array(), $filename='', $type='png', $disturb=1, $border=true) {
if (is_string($size))
$size = explode(',', $size);
$width = $size[0];
$height = $size[1];
if (is_string($font))
$font = explode(',', $font);
$fontface = $font[0];
$fontsize = $font[1];
$length = strlen($string);
$width = ($length * 9 + 10) > $width ? $length * 9 + 10 : $width;
$height = 22;
if ($type != 'gif' && function_exists('imagecreatetruecolor')) {
$im = @imagecreatetruecolor($width, $height);
} else {
$im = @imagecreate($width, $height);
}
if (empty($rgb)) {
$color = imagecolorallocate($im, 102, 104, 104);
} else {
$color = imagecolorallocate($im, $rgb[0], $rgb[1], $rgb[2]);
}
$backColor = imagecolorallocate($im, 255, 255, 255); //背景色(随机)
$borderColor = imagecolorallocate($im, 100, 100, 100); //边框色
$pointColor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); //点颜色
@imagefilledrectangle($im, 0, 0, $width - 1, $height - 1, $backColor);
@imagerectangle($im, 0, 0, $width - 1, $height - 1, $borderColor);
@imagestring($im, 5, 5, 3, $string, $color);
if (!empty($disturb)) {
// 添加干扰
if ($disturb = 1 || $disturb = 3) {
for ($i = 0; $i < 25; $i++) {
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $pointColor);
}
} elseif ($disturb = 2 || $disturb = 3) {
for ($i = 0; $i < 10; $i++) {
imagearc($im, mt_rand(-10, $width), mt_rand(-10, $height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $pointColor);
}
}
}
Image::output($im, $type, $filename);
}
/**
* 生成图像验证码
* @static
* @access public
* @param string $length 位数
* @param string $mode 类型
* @param string $type 图像格式
* @param string $width 宽度
* @param string $height 高度
* @return string
*/
static function buildImageVerify($length=4, $mode=1, $type='png', $width=48, $height=22, $verifyName='verify') {
import('ORG.Util.String');
$randval = String::randString($length, $mode);
session($verifyName, md5($randval));
$width = ($length * 10 + 10) > $width ? $length * 10 + 10 : $width;
if ($type != 'gif' && function_exists('imagecreatetruecolor')) {
$im = imagecreatetruecolor($width, $height);
} else {
$im = imagecreate($width, $height);
}
$r = Array(225, 255, 255, 223);
$g = Array(225, 236, 237, 255);
$b = Array(225, 236, 166, 125);
$key = mt_rand(0, 3);
$backColor = imagecolorallocate($im, $r[$key], $g[$key], $b[$key]); //背景色(随机)
$borderColor = imagecolorallocate($im, 100, 100, 100); //边框色
imagefilledrectangle($im, 0, 0, $width - 1, $height - 1, $backColor);
imagerectangle($im, 0, 0, $width - 1, $height - 1, $borderColor);
$stringColor = imagecolorallocate($im, mt_rand(0, 200), mt_rand(0, 120), mt_rand(0, 120));
// 干扰
for ($i = 0; $i < 10; $i++) {
imagearc($im, mt_rand(-10, $width), mt_rand(-10, $height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $stringColor);
}
for ($i = 0; $i < 25; $i++) {
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $stringColor);
}
for ($i = 0; $i < $length; $i++) {
imagestring($im, 5, $i * 10 + 5, mt_rand(1, 8), $randval{$i}, $stringColor);
}
Image::output($im, $type);
}
// 中文验证码
static function GBVerify($length=4, $type='png', $width=180, $height=50, $fontface='simhei.ttf', $verifyName='verify') {
import('ORG.Util.String');
$code = String::randString($length, 4);
$width = ($length * 45) > $width ? $length * 45 : $width;
session($verifyName, md5($code));
$im = imagecreatetruecolor($width, $height);
$borderColor = imagecolorallocate($im, 100, 100, 100); //边框色
$bkcolor = imagecolorallocate($im, 250, 250, 250);
imagefill($im, 0, 0, $bkcolor);
@imagerectangle($im, 0, 0, $width - 1, $height - 1, $borderColor);
// 干扰
for ($i = 0; $i < 15; $i++) {
$fontcolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagearc($im, mt_rand(-10, $width), mt_rand(-10, $height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $fontcolor);
}
for ($i = 0; $i < 255; $i++) {
$fontcolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $fontcolor);
}
if (!is_file($fontface)) {
$fontface = dirname(__FILE__) . "/" . $fontface;
}
for ($i = 0; $i < $length; $i++) {
$fontcolor = imagecolorallocate($im, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); //这样保证随机出来的颜色较深。
$codex = String::msubstr($code, $i, 1);
imagettftext($im, mt_rand(16, 20), mt_rand(-60, 60), 40 * $i + 20, mt_rand(30, 35), $fontcolor, $fontface, $codex);
}
Image::output($im, $type);
}
/**
* 把图像转换成字符显示
* @static
* @access public
* @param string $image 要显示的图像
* @param string $type 图像类型,默认自动获取
* @return string
*/
static function showASCIIImg($image, $string='', $type='') {
$info = Image::getImageInfo($image);
if ($info !== false) {
$type = empty($type) ? $info['type'] : $type;
unset($info);
// 载入原图
$createFun = 'ImageCreateFrom' . ($type == 'jpg' ? 'jpeg' : $type);
$im = $createFun($image);
$dx = imagesx($im);
$dy = imagesy($im);
$i = 0;
$out = '<span style="padding:0px;margin:0;line-height:100%;font-size:1px;">';
set_time_limit(0);
for ($y = 0; $y < $dy; $y++) {
for ($x = 0; $x < $dx; $x++) {
$col = imagecolorat($im, $x, $y);
$rgb = imagecolorsforindex($im, $col);
$str = empty($string) ? '*' : $string[$i++];
$out .= sprintf('<span style="margin:0px;color:#%02x%02x%02x">' . $str . '</span>', $rgb['red'], $rgb['green'], $rgb['blue']);
}
$out .= "<br>\n";
}
$out .= '</span>';
imagedestroy($im);
return $out;
}
return false;
}
/**
* 生成UPC-A条形码
* @static
* @param string $type 图像格式
* @param string $type 图像格式
* @param string $lw 单元宽度
* @param string $hi 条码高度
* @return string
*/
static function UPCA($code, $type='png', $lw=2, $hi=100) {
static $Lencode = array('0001101', '0011001', '0010011', '0111101', '0100011',
'0110001', '0101111', '0111011', '0110111', '0001011');
static $Rencode = array('1110010', '1100110', '1101100', '1000010', '1011100',
'1001110', '1010000', '1000100', '1001000', '1110100');
$ends = '101';
$center = '01010';
/* UPC-A Must be 11 digits, we compute the checksum. */
if (strlen($code) != 11) {
die("UPC-A Must be 11 digits.");
}
/* Compute the EAN-13 Checksum digit */
$ncode = '0' . $code;
$even = 0;
$odd = 0;
for ($x = 0; $x < 12; $x++) {
if ($x % 2) {
$odd += $ncode[$x];
} else {
$even += $ncode[$x];
}
}
$code.= ( 10 - (($odd * 3 + $even) % 10)) % 10;
/* Create the bar encoding using a binary string */
$bars = $ends;
$bars.=$Lencode[$code[0]];
for ($x = 1; $x < 6; $x++) {
$bars.=$Lencode[$code[$x]];
}
$bars.=$center;
for ($x = 6; $x < 12; $x++) {
$bars.=$Rencode[$code[$x]];
}
$bars.=$ends;
/* Generate the Barcode Image */
if ($type != 'gif' && function_exists('imagecreatetruecolor')) {
$im = imagecreatetruecolor($lw * 95 + 30, $hi + 30);
} else {
$im = imagecreate($lw * 95 + 30, $hi + 30);
}
$fg = ImageColorAllocate($im, 0, 0, 0);
$bg = ImageColorAllocate($im, 255, 255, 255);
ImageFilledRectangle($im, 0, 0, $lw * 95 + 30, $hi + 30, $bg);
$shift = 10;
for ($x = 0; $x < strlen($bars); $x++) {
if (($x < 10) || ($x >= 45 && $x < 50) || ($x >= 85)) {
$sh = 10;
} else {
$sh = 0;
}
if ($bars[$x] == '1') {
$color = $fg;
} else {
$color = $bg;
}
ImageFilledRectangle($im, ($x * $lw) + 15, 5, ($x + 1) * $lw + 14, $hi + 5 + $sh, $color);
}
/* Add the Human Readable Label */
ImageString($im, 4, 5, $hi - 5, $code[0], $fg);
for ($x = 0; $x < 5; $x++) {
ImageString($im, 5, $lw * (13 + $x * 6) + 15, $hi + 5, $code[$x + 1], $fg);
ImageString($im, 5, $lw * (53 + $x * 6) + 15, $hi + 5, $code[$x + 6], $fg);
}
ImageString($im, 4, $lw * 95 + 17, $hi - 5, $code[11], $fg);
/* Output the Header and Content. */
Image::output($im, $type);
}
static function output($im, $type='png', $filename='') {
header("Content-type: image/" . $type);
$ImageFun = 'image' . $type;
if (empty($filename)) {
$ImageFun($im);
} else {
$ImageFun($im, $filename);
}
imagedestroy($im);
}
}
<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | GIF.class.php 2013-03-09
// +----------------------------------------------------------------------
class GIF{
/**
* GIF帧列表
* @var array
*/
private $frames = array();
/**
* 每帧等待时间列表
* @var array
*/
private $delays = array();
/**
* 构造方法,用于解码GIF图片
* @param string $src GIF图片数据
* @param string $mod 图片数据类型
*/
public function __construct($src = null, $mod = 'url') {
if(!is_null($src)){
if('url' == $mod && is_file($src)){
$src = file_get_contents($src);
}
/* 解码GIF图片 */
try{
$de = new GIFDecoder($src);
$this->frames = $de->GIFGetFrames();
$this->delays = $de->GIFGetDelays();
} catch(Exception $e){
throw new Exception("解码GIF图片出错");
}
}
}
/**
* 设置或获取当前帧的数据
* @param string $stream 二进制数据流
* @return boolean 获取到的数据
*/
public function image($stream = null){
if(is_null($stream)){
$current = current($this->frames);
return false === $current ? reset($this->frames) : $current;
} else {
$this->frames[key($this->frames)] = $stream;
}
}
/**
* 将当前帧移动到下一帧
* @return string 当前帧数据
*/
public function nextImage(){
return next($this->frames);
}
/**
* 编码并保存当前GIF图片
* @param string $gifname 图片名称
*/
public function save($gifname){
$gif = new GIFEncoder($this->frames, $this->delays, 0, 2, 0, 0, 0, 'bin');
file_put_contents($gifname, $gif->GetAnimation());
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFEncoder Version 2.0 by László Zsidi, http://gifs.hu
::
:: This class is a rewritten 'GifMerge.class.php' version.
::
:: Modification:
:: - Simplified and easy code,
:: - Ultra fast encoding,
:: - Built-in errors,
:: - Stable working
::
::
:: Updated at 2007. 02. 13. '00.05.AM'
::
::
::
:: Try on-line GIFBuilder Form demo based on GIFEncoder.
::
:: http://gifs.hu/phpclasses/demos/GifBuilder/
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/
Class GIFEncoder {
var $GIF = "GIF89a"; /* GIF header 6 bytes */
var $VER = "GIFEncoder V2.05"; /* Encoder version */
var $BUF = Array ( );
var $LOP = 0;
var $DIS = 2;
var $COL = -1;
var $IMG = -1;
var $ERR = Array (
'ERR00'=>"Does not supported function for only one image!",
'ERR01'=>"Source is not a GIF image!",
'ERR02'=>"Unintelligible flag ",
'ERR03'=>"Does not make animation from animated GIF source",
);
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFEncoder...
::
*/
function GIFEncoder (
$GIF_src, $GIF_dly, $GIF_lop, $GIF_dis,
$GIF_red, $GIF_grn, $GIF_blu, $GIF_mod
) {
if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_tim ) ) {
printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] );
exit ( 0 );
}
$this->LOP = ( $GIF_lop > -1 ) ? $GIF_lop : 0;
$this->DIS = ( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2;
$this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ?
( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1;
for ( $i = 0; $i < count ( $GIF_src ); $i++ ) {
if ( strToLower ( $GIF_mod ) == "url" ) {
$this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) );
}
else if ( strToLower ( $GIF_mod ) == "bin" ) {
$this->BUF [ ] = $GIF_src [ $i ];
}
else {
printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod );
exit ( 0 );
}
if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) {
printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] );
exit ( 0 );
}
for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = TRUE; $k; $j++ ) {
switch ( $this->BUF [ $i ] { $j } ) {
case "!":
if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) {
printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) );
exit ( 0 );
}
break;
case ";":
$k = FALSE;
break;
}
}
}
GIFEncoder::GIFAddHeader ( );
for ( $i = 0; $i < count ( $this->BUF ); $i++ ) {
GIFEncoder::GIFAddFrames ( $i, $GIF_dly [ $i ] );
}
GIFEncoder::GIFAddFooter ( );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddHeader...
::
*/
function GIFAddHeader ( ) {
$cmap = 0;
if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) {
$cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) );
$this->GIF .= substr ( $this->BUF [ 0 ], 6, 7 );
$this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap );
$this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFEncoder::GIFWord ( $this->LOP ) . "\0";
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddFrames...
::
*/
function GIFAddFrames ( $i, $d ) {
$Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) );
$Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1;
$Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end );
$Global_len = 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 );
$Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 );
$Global_rgb = substr ( $this->BUF [ 0 ], 13,
3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ) );
$Locals_rgb = substr ( $this->BUF [ $i ], 13,
3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) );
$Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 0 ) .
chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0";
if ( $this->COL > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) {
for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) {
if (
ord ( $Locals_rgb { 3 * $j + 0 } ) == ( ( $this->COL >> 16 ) & 0xFF ) &&
ord ( $Locals_rgb { 3 * $j + 1 } ) == ( ( $this->COL >> 8 ) & 0xFF ) &&
ord ( $Locals_rgb { 3 * $j + 2 } ) == ( ( $this->COL >> 0 ) & 0xFF )
) {
$Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 1 ) .
chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . chr ( $j ) . "\x0";
break;
}
}
}
switch ( $Locals_tmp { 0 } ) {
case "!":
$Locals_img = substr ( $Locals_tmp, 8, 10 );
$Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 );
break;
case ",":
$Locals_img = substr ( $Locals_tmp, 0, 10 );
$Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 );
break;
}
if ( ord ( $this->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) {
if ( $Global_len == $Locals_len ) {
if ( GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len ) ) {
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp );
}
else {
$byte = ord ( $Locals_img { 9 } );
$byte |= 0x80;
$byte &= 0xF8;
$byte |= ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 );
$Locals_img { 9 } = chr ( $byte );
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp );
}
}
else {
$byte = ord ( $Locals_img { 9 } );
$byte |= 0x80;
$byte &= 0xF8;
$byte |= ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 );
$Locals_img { 9 } = chr ( $byte );
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp );
}
}
else {
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp );
}
$this->IMG = 1;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddFooter...
::
*/
function GIFAddFooter ( ) {
$this->GIF .= ";";
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFBlockCompare...
::
*/
function GIFBlockCompare ( $GlobalBlock, $LocalBlock, $Len ) {
for ( $i = 0; $i < $Len; $i++ ) {
if (
$GlobalBlock { 3 * $i + 0 } != $LocalBlock { 3 * $i + 0 } ||
$GlobalBlock { 3 * $i + 1 } != $LocalBlock { 3 * $i + 1 } ||
$GlobalBlock { 3 * $i + 2 } != $LocalBlock { 3 * $i + 2 }
) {
return ( 0 );
}
}
return ( 1 );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFWord...
::
*/
function GIFWord ( $int ) {
return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GetAnimation...
::
*/
function GetAnimation ( ) {
return ( $this->GIF );
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFDecoder Version 2.0 by László Zsidi, http://gifs.hu
::
:: Created at 2007. 02. 01. '07.47.AM'
::
::
::
::
:: Try on-line GIFBuilder Form demo based on GIFDecoder.
::
:: http://gifs.hu/phpclasses/demos/GifBuilder/
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/
Class GIFDecoder {
var $GIF_buffer = Array ( );
var $GIF_arrays = Array ( );
var $GIF_delays = Array ( );
var $GIF_stream = "";
var $GIF_string = "";
var $GIF_bfseek = 0;
var $GIF_screen = Array ( );
var $GIF_global = Array ( );
var $GIF_sorted;
var $GIF_colorS;
var $GIF_colorC;
var $GIF_colorF;
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFDecoder ( $GIF_pointer )
::
*/
function GIFDecoder ( $GIF_pointer ) {
$this->GIF_stream = $GIF_pointer;
GIFDecoder::GIFGetByte ( 6 ); // GIF89a
GIFDecoder::GIFGetByte ( 7 ); // Logical Screen Descriptor
$this->GIF_screen = $this->GIF_buffer;
$this->GIF_colorF = $this->GIF_buffer [ 4 ] & 0x80 ? 1 : 0;
$this->GIF_sorted = $this->GIF_buffer [ 4 ] & 0x08 ? 1 : 0;
$this->GIF_colorC = $this->GIF_buffer [ 4 ] & 0x07;
$this->GIF_colorS = 2 << $this->GIF_colorC;
if ( $this->GIF_colorF == 1 ) {
GIFDecoder::GIFGetByte ( 3 * $this->GIF_colorS );
$this->GIF_global = $this->GIF_buffer;
}
/*
*
* 05.06.2007.
* Made a little modification
*
*
- for ( $cycle = 1; $cycle; ) {
+ if ( GIFDecoder::GIFGetByte ( 1 ) ) {
- switch ( $this->GIF_buffer [ 0 ] ) {
- case 0x21:
- GIFDecoder::GIFReadExtensions ( );
- break;
- case 0x2C:
- GIFDecoder::GIFReadDescriptor ( );
- break;
- case 0x3B:
- $cycle = 0;
- break;
- }
- }
+ else {
+ $cycle = 0;
+ }
- }
*/
for ( $cycle = 1; $cycle; ) {
if ( GIFDecoder::GIFGetByte ( 1 ) ) {
switch ( $this->GIF_buffer [ 0 ] ) {
case 0x21:
GIFDecoder::GIFReadExtensions ( );
break;
case 0x2C:
GIFDecoder::GIFReadDescriptor ( );
break;
case 0x3B:
$cycle = 0;
break;
}
}
else {
$cycle = 0;
}
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFReadExtension ( )
::
*/
function GIFReadExtensions ( ) {
GIFDecoder::GIFGetByte ( 1 );
for ( ; ; ) {
GIFDecoder::GIFGetByte ( 1 );
if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) {
break;
}
GIFDecoder::GIFGetByte ( $u );
/*
* 07.05.2007.
* Implemented a new line for a new function
* to determine the originaly delays between
* frames.
*
*/
if ( $u == 4 ) {
$this->GIF_delays [ ] = ( $this->GIF_buffer [ 1 ] | $this->GIF_buffer [ 2 ] << 8 );
}
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFReadExtension ( )
::
*/
function GIFReadDescriptor ( ) {
$GIF_screen = Array ( );
GIFDecoder::GIFGetByte ( 9 );
$GIF_screen = $this->GIF_buffer;
$GIF_colorF = $this->GIF_buffer [ 8 ] & 0x80 ? 1 : 0;
if ( $GIF_colorF ) {
$GIF_code = $this->GIF_buffer [ 8 ] & 0x07;
$GIF_sort = $this->GIF_buffer [ 8 ] & 0x20 ? 1 : 0;
}
else {
$GIF_code = $this->GIF_colorC;
$GIF_sort = $this->GIF_sorted;
}
$GIF_size = 2 << $GIF_code;
$this->GIF_screen [ 4 ] &= 0x70;
$this->GIF_screen [ 4 ] |= 0x80;
$this->GIF_screen [ 4 ] |= $GIF_code;
if ( $GIF_sort ) {
$this->GIF_screen [ 4 ] |= 0x08;
}
$this->GIF_string = "GIF87a";
GIFDecoder::GIFPutByte ( $this->GIF_screen );
if ( $GIF_colorF == 1 ) {
GIFDecoder::GIFGetByte ( 3 * $GIF_size );
GIFDecoder::GIFPutByte ( $this->GIF_buffer );
}
else {
GIFDecoder::GIFPutByte ( $this->GIF_global );
}
$this->GIF_string .= chr ( 0x2C );
$GIF_screen [ 8 ] &= 0x40;
GIFDecoder::GIFPutByte ( $GIF_screen );
GIFDecoder::GIFGetByte ( 1 );
GIFDecoder::GIFPutByte ( $this->GIF_buffer );
for ( ; ; ) {
GIFDecoder::GIFGetByte ( 1 );
GIFDecoder::GIFPutByte ( $this->GIF_buffer );
if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) {
break;
}
GIFDecoder::GIFGetByte ( $u );
GIFDecoder::GIFPutByte ( $this->GIF_buffer );
}
$this->GIF_string .= chr ( 0x3B );
/*
Add frames into $GIF_stream array...
*/
$this->GIF_arrays [ ] = $this->GIF_string;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFGetByte ( $len )
::
*/
/*
*
* 05.06.2007.
* Made a little modification
*
*
- function GIFGetByte ( $len ) {
- $this->GIF_buffer = Array ( );
-
- for ( $i = 0; $i < $len; $i++ ) {
+ if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) {
+ return 0;
+ }
- $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } );
- }
+ return 1;
- }
*/
function GIFGetByte ( $len ) {
$this->GIF_buffer = Array ( );
for ( $i = 0; $i < $len; $i++ ) {
if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) {
return 0;
}
$this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } );
}
return 1;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFPutByte ( $bytes )
::
*/
function GIFPutByte ( $bytes ) {
for ( $i = 0; $i < count ( $bytes ); $i++ ) {
$this->GIF_string .= chr ( $bytes [ $i ] );
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: PUBLIC FUNCTIONS
::
::
:: GIFGetFrames ( )
::
*/
function GIFGetFrames ( ) {
return ( $this->GIF_arrays );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFGetDelays ( )
::
*/
function GIFGetDelays ( ) {
return ( $this->GIF_delays );
}
}
<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | ImageGd.class.php 2013-03-05
// +----------------------------------------------------------------------
class ImageGd{
/**
* 图像资源对象
* @var resource
*/
private $img;
/**
* 图像信息,包括width,height,type,mime,size
* @var array
*/
private $info;
/**
* 构造方法,可用于打开一张图像
* @param string $imgname 图像路径
*/
public function __construct($imgname = null) {
$imgname && $this->open($imgname);
}
/**
* 打开一张图像
* @param string $imgname 图像路径
*/
public function open($imgname){
//检测图像文件
if(!is_file($imgname)) throw new Exception('不存在的图像文件');
//获取图像信息
$info = getimagesize($imgname);
//检测图像合法性
if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){
throw new Exception('非法图像文件');
}
//设置图像信息
$this->info = array(
'width' => $info[0],
'height' => $info[1],
'type' => image_type_to_extension($info[2], false),
'mime' => $info['mime'],
);
//销毁已存在的图像
empty($this->img) || imagedestroy($this->img);
//打开图像
if('gif' == $this->info['type']){
require_once 'GIF.class.php';
$this->gif = new GIF($imgname);
$this->img = imagecreatefromstring($this->gif->image());
} else {
$fun = "imagecreatefrom{$this->info['type']}";
$this->img = $fun($imgname);
}
}
/**
* 保存图像
* @param string $imgname 图像保存名称
* @param string $type 图像类型
* @param boolean $interlace 是否对JPEG类型图像设置隔行扫描
*/
public function save($imgname, $type = null, $interlace = true){
if(empty($this->img)) throw new Exception('没有可以被保存的图像资源');
//自动获取图像类型
if(is_null($type)){
$type = $this->info['type'];
} else {
$type = strtolower($type);
}
//JPEG图像设置隔行扫描
if('jpeg' == $type || 'jpg' == $type){
$type = 'jpeg';
imageinterlace($this->img, $interlace);
}
//保存图像
if('gif' == $type && !empty($this->gif)){
$this->gif->save($imgname);
} else {
$fun = "image{$type}";
$fun($this->img, $imgname);
}
}
/**
* 返回图像宽度
* @return integer 图像宽度
*/
public function width(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['width'];
}
/**
* 返回图像高度
* @return integer 图像高度
*/
public function height(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['height'];
}
/**
* 返回图像类型
* @return string 图像类型
*/
public function type(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['type'];
}
/**
* 返回图像MIME类型
* @return string 图像MIME类型
*/
public function mime(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['mime'];
}
/**
* 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度
* @return array 图像尺寸
*/
public function size(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return array($this->info['width'], $this->info['height']);
}
/**
* 裁剪图像
* @param integer $w 裁剪区域宽度
* @param integer $h 裁剪区域高度
* @param integer $x 裁剪区域x坐标
* @param integer $y 裁剪区域y坐标
* @param integer $width 图像保存宽度
* @param integer $height 图像保存高度
*/
public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){
if(empty($this->img)) throw new Exception('没有可以被裁剪的图像资源');
//设置保存尺寸
empty($width) && $width = $w;
empty($height) && $height = $h;
do {
//创建新图像
$img = imagecreatetruecolor($width, $height);
// 调整默认颜色
$color = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $color);
//裁剪
imagecopyresampled($img, $this->img, 0, 0, $x, $y, $width, $height, $w, $h);
imagedestroy($this->img); //销毁原图
//设置新图像
$this->img = $img;
} while(!empty($this->gif) && $this->gifNext());
$this->info['width'] = $width;
$this->info['height'] = $height;
}
/**
* 生成缩略图
* @param integer $width 缩略图最大宽度
* @param integer $height 缩略图最大高度
* @param integer $type 缩略图裁剪类型
*/
public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){
if(empty($this->img)) throw new Exception('没有可以被缩略的图像资源');
//原图宽度和高度
$w = $this->info['width'];
$h = $this->info['height'];
/* 计算缩略图生成的必要参数 */
switch ($type) {
/* 等比例缩放 */
case THINKIMAGE_THUMB_SCALING:
//原图尺寸小于缩略图尺寸则不进行缩略
if($w < $width && $h < $height) return;
//计算缩放比例
$scale = min($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$x = $y = 0;
$width = $w * $scale;
$height = $h * $scale;
break;
/* 居中裁剪 */
case THINKIMAGE_THUMB_CENTER:
//计算缩放比例
$scale = max($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$w = $width/$scale;
$h = $height/$scale;
$x = ($this->info['width'] - $w)/2;
$y = ($this->info['height'] - $h)/2;
break;
/* 左上角裁剪 */
case THINKIMAGE_THUMB_NORTHWEST:
//计算缩放比例
$scale = max($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$x = $y = 0;
$w = $width/$scale;
$h = $height/$scale;
break;
/* 右下角裁剪 */
case THINKIMAGE_THUMB_SOUTHEAST:
//计算缩放比例
$scale = max($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$w = $width/$scale;
$h = $height/$scale;
$x = $this->info['width'] - $w;
$y = $this->info['height'] - $h;
break;
/* 填充 */
case THINKIMAGE_THUMB_FILLED:
//计算缩放比例
if($w < $width && $h < $height){
$scale = 1;
} else {
$scale = min($width/$w, $height/$h);
}
//设置缩略图的坐标及宽度和高度
$neww = $w * $scale;
$newh = $h * $scale;
$posx = ($width - $w * $scale)/2;
$posy = ($height - $h * $scale)/2;
do{
//创建新图像
$img = imagecreatetruecolor($width, $height);
// 调整默认颜色
$color = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $color);
//裁剪
imagecopyresampled($img, $this->img, $posx, $posy, $x, $y, $neww, $newh, $w, $h);
imagedestroy($this->img); //销毁原图
$this->img = $img;
} while(!empty($this->gif) && $this->gifNext());
$this->info['width'] = $width;
$this->info['height'] = $height;
return;
/* 固定 */
case THINKIMAGE_THUMB_FIXED:
$x = $y = 0;
break;
default:
throw new Exception('不支持的缩略图裁剪类型');
}
/* 裁剪图像 */
$this->crop($w, $h, $x, $y, $width, $height);
}
/**
* 添加水印
* @param string $source 水印图片路径
* @param integer $locate 水印位置
* @param integer $alpha 水印透明度
*/
public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){
//资源检测
if(empty($this->img)) throw new Exception('没有可以被添加水印的图像资源');
if(!is_file($source)) throw new Exception('水印图像不存在');
//获取水印图像信息
$info = getimagesize($source);
if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){
throw new Exception('非法水印文件');
}
//创建水印图像资源
$fun = 'imagecreatefrom' . image_type_to_extension($info[2], false);
$water = $fun($source);
//设定水印图像的混色模式
imagealphablending($water, true);
/* 设定水印位置 */
switch ($locate) {
/* 右下角水印 */
case THINKIMAGE_WATER_SOUTHEAST:
$x = $this->info['width'] - $info[0];
$y = $this->info['height'] - $info[1];
break;
/* 左下角水印 */
case THINKIMAGE_WATER_SOUTHWEST:
$x = 0;
$y = $this->info['height'] - $info[1];
break;
/* 左上角水印 */
case THINKIMAGE_WATER_NORTHWEST:
$x = $y = 0;
break;
/* 右上角水印 */
case THINKIMAGE_WATER_NORTHEAST:
$x = $this->info['width'] - $info[0];
$y = 0;
break;
/* 居中水印 */
case THINKIMAGE_WATER_CENTER:
$x = ($this->info['width'] - $info[0])/2;
$y = ($this->info['height'] - $info[1])/2;
break;
/* 下居中水印 */
case THINKIMAGE_WATER_SOUTH:
$x = ($this->info['width'] - $info[0])/2;
$y = $this->info['height'] - $info[1];
break;
/* 右居中水印 */
case THINKIMAGE_WATER_EAST:
$x = $this->info['width'] - $info[0];
$y = ($this->info['height'] - $info[1])/2;
break;
/* 上居中水印 */
case THINKIMAGE_WATER_NORTH:
$x = ($this->info['width'] - $info[0])/2;
$y = 0;
break;
/* 左居中水印 */
case THINKIMAGE_WATER_WEST:
$x = 0;
$y = ($this->info['height'] - $info[1])/2;
break;
default:
/* 自定义水印坐标 */
if(is_array($locate)){
list($x, $y) = $locate;
} else {
throw new Exception('不支持的水印位置类型');
}
}
do{
//添加水印
$src = imagecreatetruecolor($info[0], $info[1]);
// 调整默认颜色
$color = imagecolorallocate($src, 255, 255, 255);
imagefill($src, 0, 0, $color);
imagecopy($src, $this->img, 0, 0, $x, $y, $info[0], $info[1]);
imagecopy($src, $water, 0, 0, 0, 0, $info[0], $info[1]);
imagecopymerge($this->img, $src, $x, $y, 0, 0, $info[0], $info[1], 100);
//销毁零时图片资源
imagedestroy($src);
} while(!empty($this->gif) && $this->gifNext());
//销毁水印资源
imagedestroy($water);
}
/**
* 图像添加文字
* @param string $text 添加的文字
* @param string $font 字体路径
* @param integer $size 字号
* @param string $color 文字颜色
* @param integer $locate 文字写入位置
* @param integer $offset 文字相对当前位置的偏移量
* @param integer $angle 文字倾斜角度
*/
public function text($text, $font, $size, $color = '#00000000',
$locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){
//资源检测
if(empty($this->img)) throw new Exception('没有可以被写入文字的图像资源');
if(!is_file($font)) throw new Exception("不存在的字体文件:{$font}");
//获取文字信息
$info = imagettfbbox($size, $angle, $font, $text);
$minx = min($info[0], $info[2], $info[4], $info[6]);
$maxx = max($info[0], $info[2], $info[4], $info[6]);
$miny = min($info[1], $info[3], $info[5], $info[7]);
$maxy = max($info[1], $info[3], $info[5], $info[7]);
/* 计算文字初始坐标和尺寸 */
$x = $minx;
$y = abs($miny);
$w = $maxx - $minx;
$h = $maxy - $miny;
/* 设定文字位置 */
switch ($locate) {
/* 右下角文字 */
case THINKIMAGE_WATER_SOUTHEAST:
$x += $this->info['width'] - $w;
$y += $this->info['height'] - $h;
break;
/* 左下角文字 */
case THINKIMAGE_WATER_SOUTHWEST:
$y += $this->info['height'] - $h;
break;
/* 左上角文字 */
case THINKIMAGE_WATER_NORTHWEST:
// 起始坐标即为左上角坐标,无需调整
break;
/* 右上角文字 */
case THINKIMAGE_WATER_NORTHEAST:
$x += $this->info['width'] - $w;
break;
/* 居中文字 */
case THINKIMAGE_WATER_CENTER:
$x += ($this->info['width'] - $w)/2;
$y += ($this->info['height'] - $h)/2;
break;
/* 下居中文字 */
case THINKIMAGE_WATER_SOUTH:
$x += ($this->info['width'] - $w)/2;
$y += $this->info['height'] - $h;
break;
/* 右居中文字 */
case THINKIMAGE_WATER_EAST:
$x += $this->info['width'] - $w;
$y += ($this->info['height'] - $h)/2;
break;
/* 上居中文字 */
case THINKIMAGE_WATER_NORTH:
$x += ($this->info['width'] - $w)/2;
break;
/* 左居中文字 */
case THINKIMAGE_WATER_WEST:
$y += ($this->info['height'] - $h)/2;
break;
default:
/* 自定义文字坐标 */
if(is_array($locate)){
list($posx, $posy) = $locate;
$x += $posx;
$y += $posy;
} else {
throw new Exception('不支持的文字位置类型');
}
}
/* 设置偏移量 */
if(is_array($offset)){
$offset = array_map('intval', $offset);
list($ox, $oy) = $offset;
} else{
$offset = intval($offset);
$ox = $oy = $offset;
}
/* 设置颜色 */
if(is_string($color) && 0 === strpos($color, '#')){
$color = str_split(substr($color, 1), 2);
$color = array_map('hexdec', $color);
if(empty($color[3]) || $color[3] > 127){
$color[3] = 0;
}
} elseif (!is_array($color)) {
throw new Exception('错误的颜色值');
}
do{
/* 写入文字 */
$col = imagecolorallocatealpha($this->img, $color[0], $color[1], $color[2], $color[3]);
imagettftext($this->img, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text);
} while(!empty($this->gif) && $this->gifNext());
}
/* 切换到GIF的下一帧并保存当前帧,内部使用 */
private function gifNext(){
ob_start();
ob_implicit_flush(0);
imagegif($this->img);
$img = ob_get_clean();
$this->gif->image($img);
$next = $this->gif->nextImage();
if($next){
$this->img = imagecreatefromstring($next);
return $next;
} else {
$this->img = imagecreatefromstring($this->gif->image());
return false;
}
}
/**
* 析构方法,用于销毁图像资源
*/
public function __destruct() {
empty($this->img) || imagedestroy($this->img);
}
}
<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | ImageImagick.class.php 2013-03-06
// +----------------------------------------------------------------------
class ImageImagick{
/**
* 图像资源对象
* @var resource
*/
private $img;
/**
* 图像信息,包括width,height,type,mime,size
* @var array
*/
private $info;
/**
* 构造方法,可用于打开一张图像
* @param string $imgname 图像路径
*/
public function __construct($imgname = null) {
$imgname && $this->open($imgname);
}
/**
* 打开一张图像
* @param string $imgname 图像路径
*/
public function open($imgname){
//检测图像文件
if(!is_file($imgname)) throw new Exception('不存在的图像文件');
//销毁已存在的图像
empty($this->img) || $this->img->destroy();
//载入图像
$this->img = new Imagick(realpath($imgname));
//设置图像信息
$this->info = array(
'width' => $this->img->getImageWidth(),
'height' => $this->img->getImageHeight(),
'type' => strtolower($this->img->getImageFormat()),
'mime' => $this->img->getImageMimeType(),
);
}
/**
* 保存图像
* @param string $imgname 图像保存名称
* @param string $type 图像类型
* @param boolean $interlace 是否对JPEG类型图像设置隔行扫描
*/
public function save($imgname, $type = null, $interlace = true){
if(empty($this->img)) throw new Exception('没有可以被保存的图像资源');
//设置图片类型
if(is_null($type)){
$type = $this->info['type'];
} else {
$type = strtolower($type);
$this->img->setImageFormat($type);
}
//JPEG图像设置隔行扫描
if('jpeg' == $type || 'jpg' == $type){
$this->img->setImageInterlaceScheme(1);
}
//去除图像配置信息
$this->img->stripImage();
//保存图像
$imgname = realpath(dirname($imgname)) . '/' . basename($imgname); //强制绝对路径
if ('gif' == $type) {
$this->img->writeImages($imgname, true);
} else {
$this->img->writeImage($imgname);
}
}
/**
* 返回图像宽度
* @return integer 图像宽度
*/
public function width(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['width'];
}
/**
* 返回图像高度
* @return integer 图像高度
*/
public function height(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['height'];
}
/**
* 返回图像类型
* @return string 图像类型
*/
public function type(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['type'];
}
/**
* 返回图像MIME类型
* @return string 图像MIME类型
*/
public function mime(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return $this->info['mime'];
}
/**
* 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度
* @return array 图像尺寸
*/
public function size(){
if(empty($this->img)) throw new Exception('没有指定图像资源');
return array($this->info['width'], $this->info['height']);
}
/**
* 裁剪图像
* @param integer $w 裁剪区域宽度
* @param integer $h 裁剪区域高度
* @param integer $x 裁剪区域x坐标
* @param integer $y 裁剪区域y坐标
* @param integer $width 图像保存宽度
* @param integer $height 图像保存高度
*/
public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){
if(empty($this->img)) throw new Exception('没有可以被裁剪的图像资源');
//设置保存尺寸
empty($width) && $width = $w;
empty($height) && $height = $h;
//裁剪图片
if('gif' == $this->info['type']){
$img = $this->img->coalesceImages();
$this->img->destroy(); //销毁原图
//循环裁剪每一帧
do {
$this->_crop($w, $h, $x, $y, $width, $height, $img);
} while ($img->nextImage());
//压缩图片
$this->img = $img->deconstructImages();
$img->destroy(); //销毁零时图片
} else {
$this->_crop($w, $h, $x, $y, $width, $height);
}
}
/* 裁剪图片,内部调用 */
private function _crop($w, $h, $x, $y, $width, $height, $img = null){
is_null($img) && $img = $this->img;
//裁剪
$info = $this->info;
if($x != 0 || $y != 0 || $w != $info['width'] || $h != $info['height']){
$img->cropImage($w, $h, $x, $y);
$img->setImagePage($w, $h, 0, 0); //调整画布和图片一致
}
//调整大小
if($w != $width || $h != $height){
$img->sampleImage($width, $height);
}
//设置缓存尺寸
$this->info['width'] = $w;
$this->info['height'] = $h;
}
/**
* 生成缩略图
* @param integer $width 缩略图最大宽度
* @param integer $height 缩略图最大高度
* @param integer $type 缩略图裁剪类型
*/
public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){
if(empty($this->img)) throw new Exception('没有可以被缩略的图像资源');
//原图宽度和高度
$w = $this->info['width'];
$h = $this->info['height'];
/* 计算缩略图生成的必要参数 */
switch ($type) {
/* 等比例缩放 */
case THINKIMAGE_THUMB_SCALING:
//原图尺寸小于缩略图尺寸则不进行缩略
if($w < $width && $h < $height) return;
//计算缩放比例
$scale = min($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$x = $y = 0;
$width = $w * $scale;
$height = $h * $scale;
break;
/* 居中裁剪 */
case THINKIMAGE_THUMB_CENTER:
//计算缩放比例
$scale = max($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$w = $width/$scale;
$h = $height/$scale;
$x = ($this->info['width'] - $w)/2;
$y = ($this->info['height'] - $h)/2;
break;
/* 左上角裁剪 */
case THINKIMAGE_THUMB_NORTHWEST:
//计算缩放比例
$scale = max($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$x = $y = 0;
$w = $width/$scale;
$h = $height/$scale;
break;
/* 右下角裁剪 */
case THINKIMAGE_THUMB_SOUTHEAST:
//计算缩放比例
$scale = max($width/$w, $height/$h);
//设置缩略图的坐标及宽度和高度
$w = $width/$scale;
$h = $height/$scale;
$x = $this->info['width'] - $w;
$y = $this->info['height'] - $h;
break;
/* 填充 */
case THINKIMAGE_THUMB_FILLED:
//计算缩放比例
if($w < $width && $h < $height){
$scale = 1;
} else {
$scale = min($width/$w, $height/$h);
}
//设置缩略图的坐标及宽度和高度
$neww = $w * $scale;
$newh = $h * $scale;
$posx = ($width - $w * $scale)/2;
$posy = ($height - $h * $scale)/2;
//创建一张新图像
$newimg = new Imagick();
$newimg->newImage($width, $height, 'white', $this->info['type']);
if('gif' == $this->info['type']){
$imgs = $this->img->coalesceImages();
$img = new Imagick();
$this->img->destroy(); //销毁原图
//循环填充每一帧
do {
//填充图像
$image = $this->_fill($newimg, $posx, $posy, $neww, $newh, $imgs);
$img->addImage($image);
$img->setImageDelay($imgs->getImageDelay());
$img->setImagePage($width, $height, 0, 0);
$image->destroy(); //销毁零时图片
} while ($imgs->nextImage());
//压缩图片
$this->img->destroy();
$this->img = $img->deconstructImages();
$imgs->destroy(); //销毁零时图片
$img->destroy(); //销毁零时图片
} else {
//填充图像
$img = $this->_fill($newimg, $posx, $posy, $neww, $newh);
//销毁原图
$this->img->destroy();
$this->img = $img;
}
//设置新图像属性
$this->info['width'] = $width;
$this->info['height'] = $height;
return;
/* 固定 */
case THINKIMAGE_THUMB_FIXED:
$x = $y = 0;
break;
default:
throw new Exception('不支持的缩略图裁剪类型');
}
/* 裁剪图像 */
$this->crop($w, $h, $x, $y, $width, $height);
}
/* 填充指定图像,内部使用 */
private function _fill($newimg, $posx, $posy, $neww, $newh, $img = null){
is_null($img) && $img = $this->img;
/* 将指定图片绘入空白图片 */
$draw = new ImagickDraw();
$draw->composite($img->getImageCompose(), $posx, $posy, $neww, $newh, $img);
$image = $newimg->clone();
$image->drawImage($draw);
$draw->destroy();
return $image;
}
/**
* 添加水印
* @param string $source 水印图片路径
* @param integer $locate 水印位置
* @param integer $alpha 水印透明度
*/
public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){
//资源检测
if(empty($this->img)) throw new Exception('没有可以被添加水印的图像资源');
if(!is_file($source)) throw new Exception('水印图像不存在');
//创建水印图像资源
$water = new Imagick(realpath($source));
$info = array($water->getImageWidth(), $water->getImageHeight());
/* 设定水印位置 */
switch ($locate) {
/* 右下角水印 */
case THINKIMAGE_WATER_SOUTHEAST:
$x = $this->info['width'] - $info[0];
$y = $this->info['height'] - $info[1];
break;
/* 左下角水印 */
case THINKIMAGE_WATER_SOUTHWEST:
$x = 0;
$y = $this->info['height'] - $info[1];
break;
/* 左上角水印 */
case THINKIMAGE_WATER_NORTHWEST:
$x = $y = 0;
break;
/* 右上角水印 */
case THINKIMAGE_WATER_NORTHEAST:
$x = $this->info['width'] - $info[0];
$y = 0;
break;
/* 居中水印 */
case THINKIMAGE_WATER_CENTER:
$x = ($this->info['width'] - $info[0])/2;
$y = ($this->info['height'] - $info[1])/2;
break;
/* 下居中水印 */
case THINKIMAGE_WATER_SOUTH:
$x = ($this->info['width'] - $info[0])/2;
$y = $this->info['height'] - $info[1];
break;
/* 右居中水印 */
case THINKIMAGE_WATER_EAST:
$x = $this->info['width'] - $info[0];
$y = ($this->info['height'] - $info[1])/2;
break;
/* 上居中水印 */
case THINKIMAGE_WATER_NORTH:
$x = ($this->info['width'] - $info[0])/2;
$y = 0;
break;
/* 左居中水印 */
case THINKIMAGE_WATER_WEST:
$x = 0;
$y = ($this->info['height'] - $info[1])/2;
break;
default:
/* 自定义水印坐标 */
if(is_array($locate)){
list($x, $y) = $locate;
} else {
throw new Exception('不支持的水印位置类型');
}
}
//创建绘图资源
$draw = new ImagickDraw();
$draw->composite($water->getImageCompose(), $x, $y, $info[0], $info[1], $water);
if('gif' == $this->info['type']){
$img = $this->img->coalesceImages();
$this->img->destroy(); //销毁原图
do{
//添加水印
$img->drawImage($draw);
} while ($img->nextImage());
//压缩图片
$this->img = $img->deconstructImages();
$img->destroy(); //销毁零时图片
} else {
//添加水印
$this->img->drawImage($draw);
}
//销毁水印资源
$draw->destroy();
$water->destroy();
}
/**
* 图像添加文字
* @param string $text 添加的文字
* @param string $font 字体路径
* @param integer $size 字号
* @param string $color 文字颜色
* @param integer $locate 文字写入位置
* @param integer $offset 文字相对当前位置的偏移量
* @param integer $angle 文字倾斜角度
*/
public function text($text, $font, $size, $color = '#00000000',
$locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){
//资源检测
if(empty($this->img)) throw new Exception('没有可以被写入文字的图像资源');
if(!is_file($font)) throw new Exception("不存在的字体文件:{$font}");
//获取颜色和透明度
if(is_array($color)){
$color = array_map('dechex', $color);
foreach ($color as &$value) {
$value = str_pad($value, 2, '0', STR_PAD_LEFT);
}
$color = '#' . implode('', $color);
} elseif(!is_string($color) || 0 !== strpos($color, '#')) {
throw new Exception('错误的颜色值');
}
$col = substr($color, 0, 7);
$alp = strlen($color) == 9 ? substr($color, -2) : 0;
//获取文字信息
$draw = new ImagickDraw();
$draw->setFont(realpath($font));
$draw->setFontSize($size);
$draw->setFillColor($col);
$draw->setFillAlpha(1-hexdec($alp)/127);
$draw->setTextAntialias(true);
$draw->setStrokeAntialias(true);
$metrics = $this->img->queryFontMetrics($draw, $text);
/* 计算文字初始坐标和尺寸 */
$x = 0;
$y = $metrics['ascender'];
$w = $metrics['textWidth'];
$h = $metrics['textHeight'];
/* 设定文字位置 */
switch ($locate) {
/* 右下角文字 */
case THINKIMAGE_WATER_SOUTHEAST:
$x += $this->info['width'] - $w;
$y += $this->info['height'] - $h;
break;
/* 左下角文字 */
case THINKIMAGE_WATER_SOUTHWEST:
$y += $this->info['height'] - $h;
break;
/* 左上角文字 */
case THINKIMAGE_WATER_NORTHWEST:
// 起始坐标即为左上角坐标,无需调整
break;
/* 右上角文字 */
case THINKIMAGE_WATER_NORTHEAST:
$x += $this->info['width'] - $w;
break;
/* 居中文字 */
case THINKIMAGE_WATER_CENTER:
$x += ($this->info['width'] - $w)/2;
$y += ($this->info['height'] - $h)/2;
break;
/* 下居中文字 */
case THINKIMAGE_WATER_SOUTH:
$x += ($this->info['width'] - $w)/2;
$y += $this->info['height'] - $h;
break;
/* 右居中文字 */
case THINKIMAGE_WATER_EAST:
$x += $this->info['width'] - $w;
$y += ($this->info['height'] - $h)/2;
break;
/* 上居中文字 */
case THINKIMAGE_WATER_NORTH:
$x += ($this->info['width'] - $w)/2;
break;
/* 左居中文字 */
case THINKIMAGE_WATER_WEST:
$y += ($this->info['height'] - $h)/2;
break;
default:
/* 自定义文字坐标 */
if(is_array($locate)){
list($posx, $posy) = $locate;
$x += $posx;
$y += $posy;
} else {
throw new Exception('不支持的文字位置类型');
}
}
/* 设置偏移量 */
if(is_array($offset)){
$offset = array_map('intval', $offset);
list($ox, $oy) = $offset;
} else{
$offset = intval($offset);
$ox = $oy = $offset;
}
/* 写入文字 */
if('gif' == $this->info['type']){
$img = $this->img->coalesceImages();
$this->img->destroy(); //销毁原图
do{
$img->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text);
} while ($img->nextImage());
//压缩图片
$this->img = $img->deconstructImages();
$img->destroy(); //销毁零时图片
} else {
$this->img->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text);
}
$draw->destroy();
}
/**
* 析构方法,用于销毁图像资源
*/
public function __destruct() {
empty($this->img) || $this->img->destroy();
}
}

ThinkImage 是什么?

ThinkImage是一个PHP图片处理工具。目前支持图片缩略图,图片裁剪,图片添加水印和文字水印等功能。可自由切换系统支持的图片处理工具,目前支持GD库和Imagick库。在GD库下也能良好的处理GIF图片。

ThinkImage 怎么使用?

ThinkImage的使用比较简单,你只需要引入ThinkImage类,实例化一个ThinkImage的对象并传入要使用的图片处理库类型和要处理的图片,就可以对图片进行操作了。关键代码如下:(以ThinkPHP为例,非ThinkPHP框架请使用PHP原生的文件引入方法)

//引入图片处理库
import('ORG.Util.Image.ThinkImage'); 
//使用GD库来处理1.gif图片
$img = new ThinkImage(THINKIMAGE_GD, './1.gif'); 
//将图片裁剪为440x440并保存为corp.gif
$img->crop(440, 440)->save('./crop.gif');
//给裁剪后的图片添加图片水印,位置为右下角,保存为water.gif
$img->water('./11.png', THINKIMAGE_WATER_SOUTHEAST)->save("water.gif");
//给原图添加水印并保存为water_o.gif(需要重新打开原图)
$img->open('./1.gif')->water('./11.png', THINKIMAGE_WATER_SOUTHEAST)->save("water_o.gif");

ThinkImage有哪些可以使用的常量?

ThinkImage提供了部分常量,方便记忆,在使用的过程中,可以直接使用常量或对应的整型值。

/* 驱动相关常量定义 */
define('THINKIMAGE_GD',      1); //常量,标识GD库类型
define('THINKIMAGE_IMAGICK', 2); //常量,标识imagick库类型

/* 缩略图相关常量定义 */
define('THINKIMAGE_THUMB_SCALING',   1); //常量,标识缩略图等比例缩放类型
define('THINKIMAGE_THUMB_FILLED',    2); //常量,标识缩略图缩放后填充类型
define('THINKIMAGE_THUMB_CENTER',    3); //常量,标识缩略图居中裁剪类型
define('THINKIMAGE_THUMB_NORTHWEST', 4); //常量,标识缩略图左上角裁剪类型
define('THINKIMAGE_THUMB_SOUTHEAST', 5); //常量,标识缩略图右下角裁剪类型
define('THINKIMAGE_THUMB_FIXED',     6); //常量,标识缩略图固定尺寸缩放类型

/* 水印相关常量定义 */
define('THINKIMAGE_WATER_NORTHWEST', 1); //常量,标识左上角水印
define('THINKIMAGE_WATER_NORTH',     2); //常量,标识上居中水印
define('THINKIMAGE_WATER_NORTHEAST', 3); //常量,标识右上角水印
define('THINKIMAGE_WATER_WEST',      4); //常量,标识左居中水印
define('THINKIMAGE_WATER_CENTER',    5); //常量,标识居中水印
define('THINKIMAGE_WATER_EAST',      6); //常量,标识右居中水印
define('THINKIMAGE_WATER_SOUTHWEST', 7); //常量,标识左下角水印
define('THINKIMAGE_WATER_SOUTH',     8); //常量,标识下居中水印
define('THINKIMAGE_WATER_SOUTHEAST', 9); //常量,标识右下角水印

ThinkImage有哪些可以使用的方法?

以下方法为ThinkImage提供的图片处理接口,可直接使用。

打开一幅图像

/**
 * @param  string $imgname 图片路径
 * @return Object          当前图片处理库对象
 */
public function open($imgname){}

保存图片

/**
 * @param  string  $imgname   图片保存名称
 * @param  string  $type      图片类型
 * @param  boolean $interlace 是否对JPEG类型图片设置隔行扫描
 * @return Object             当前图片处理库对象
 */
public function save($imgname, $type = null, $interlace = true){}

获取图片宽度

/**
 * @return integer 图片宽度
 */
public function width(){}

获取图片高度

/**
 * @return integer 图片高度
 */
public function height(){}

获取图像类型

/**
 * @return string 图片类型
 */
public function type(){}

获取图像MIME类型

/**
 * @return string 图像MIME类型
 */
public function mime(){}

获取图像尺寸数组 0 - 图片宽度,1 - 图片高度

/**
 * @return array 图片尺寸
 */
public function size(){}

裁剪图片

/**
 * @param  integer $w      裁剪区域宽度
 * @param  integer $h      裁剪区域高度
 * @param  integer $x      裁剪区域x坐标
 * @param  integer $y      裁剪区域y坐标
 * @param  integer $width  图片保存宽度
 * @param  integer $height 图片保存高度
 * @return Object          当前图片处理库对象
 */
public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){}

生成缩略图

/**
 * @param  integer $width  缩略图最大宽度
 * @param  integer $height 缩略图最大高度
 * @param  integer $type   缩略图裁剪类型
 * @return Object          当前图片处理库对象
 */
public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){}

添加水印

/**
 * @param  string  $source 水印图片路径
 * @param  integer $locate 水印位置
 * @param  integer $alpha  水印透明度
 * @return Object          当前图片处理库对象
 */
public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){}

图像添加文字

/**
 * @param  string  $text   添加的文字
 * @param  string  $font   字体路径
 * @param  integer $size   字号
 * @param  string  $color  文字颜色
 * @param  integer $locate 文字写入位置
 * @param  integer $offset 文字相对当前位置的偏移量
 * @param  integer $angle  文字倾斜角度
 * @return Object          当前图片处理库对象
 */
public function text($text, $font, $size, $color = '#00000000', 
    $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){}
<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | ThinkImage.class.php 2013-03-05
// +----------------------------------------------------------------------
/* 驱动相关常量定义 */
define('THINKIMAGE_GD', 1); //常量,标识GD库类型
define('THINKIMAGE_IMAGICK', 2); //常量,标识imagick库类型
/* 缩略图相关常量定义 */
define('THINKIMAGE_THUMB_SCALING', 1); //常量,标识缩略图等比例缩放类型
define('THINKIMAGE_THUMB_FILLED', 2); //常量,标识缩略图缩放后填充类型
define('THINKIMAGE_THUMB_CENTER', 3); //常量,标识缩略图居中裁剪类型
define('THINKIMAGE_THUMB_NORTHWEST', 4); //常量,标识缩略图左上角裁剪类型
define('THINKIMAGE_THUMB_SOUTHEAST', 5); //常量,标识缩略图右下角裁剪类型
define('THINKIMAGE_THUMB_FIXED', 6); //常量,标识缩略图固定尺寸缩放类型
/* 水印相关常量定义 */
define('THINKIMAGE_WATER_NORTHWEST', 1); //常量,标识左上角水印
define('THINKIMAGE_WATER_NORTH', 2); //常量,标识上居中水印
define('THINKIMAGE_WATER_NORTHEAST', 3); //常量,标识右上角水印
define('THINKIMAGE_WATER_WEST', 4); //常量,标识左居中水印
define('THINKIMAGE_WATER_CENTER', 5); //常量,标识居中水印
define('THINKIMAGE_WATER_EAST', 6); //常量,标识右居中水印
define('THINKIMAGE_WATER_SOUTHWEST', 7); //常量,标识左下角水印
define('THINKIMAGE_WATER_SOUTH', 8); //常量,标识下居中水印
define('THINKIMAGE_WATER_SOUTHEAST', 9); //常量,标识右下角水印
/**
* 图片处理驱动类,可配置图片处理库
* 目前支持GD库和imagick
* @author 麦当苗儿 <zuojiazi.cn@gmail.com>
*/
class ThinkImage{
/**
* 图片资源
* @var resource
*/
private $img;
/**
* 构造方法,用于实例化一个图片处理对象
* @param string $type 要使用的类库,默认使用GD库
*/
public function __construct($type = THINKIMAGE_GD, $imgname = null){
/* 判断调用库的类型 */
switch ($type) {
case THINKIMAGE_GD:
$class = 'ImageGd';
break;
case THINKIMAGE_IMAGICK:
$class = 'ImageImagick';
break;
default:
throw new Exception('不支持的图片处理库类型');
}
/* 引入处理库,实例化图片处理对象 */
require_once "Driver/{$class}.class.php";
$this->img = new $class($imgname);
}
/**
* 打开一幅图像
* @param string $imgname 图片路径
* @return Object 当前图片处理库对象
*/
public function open($imgname){
$this->img->open($imgname);
return $this;
}
/**
* 保存图片
* @param string $imgname 图片保存名称
* @param string $type 图片类型
* @param boolean $interlace 是否对JPEG类型图片设置隔行扫描
* @return Object 当前图片处理库对象
*/
public function save($imgname, $type = null, $interlace = true){
$this->img->save($imgname, $type, $interlace);
return $this;
}
/**
* 返回图片宽度
* @return integer 图片宽度
*/
public function width(){
return $this->img->width();
}
/**
* 返回图片高度
* @return integer 图片高度
*/
public function height(){
return $this->img->height();
}
/**
* 返回图像类型
* @return string 图片类型
*/
public function type(){
return $this->img->type();
}
/**
* 返回图像MIME类型
* @return string 图像MIME类型
*/
public function mime(){
return $this->img->mime();
}
/**
* 返回图像尺寸数组 0 - 图片宽度,1 - 图片高度
* @return array 图片尺寸
*/
public function size(){
return $this->img->size();
}
/**
* 裁剪图片
* @param integer $w 裁剪区域宽度
* @param integer $h 裁剪区域高度
* @param integer $x 裁剪区域x坐标
* @param integer $y 裁剪区域y坐标
* @param integer $width 图片保存宽度
* @param integer $height 图片保存高度
* @return Object 当前图片处理库对象
*/
public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){
$this->img->crop($w, $h, $x, $y, $width, $height);
return $this;
}
/**
* 生成缩略图
* @param integer $width 缩略图最大宽度
* @param integer $height 缩略图最大高度
* @param integer $type 缩略图裁剪类型
* @return Object 当前图片处理库对象
*/
public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){
$this->img->thumb($width, $height, $type);
return $this;
}
/**
* 添加水印
* @param string $source 水印图片路径
* @param integer $locate 水印位置
* @param integer $alpha 水印透明度
* @return Object 当前图片处理库对象
*/
public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){
$this->img->water($source, $locate);
return $this;
}
/**
* 图像添加文字
* @param string $text 添加的文字
* @param string $font 字体路径
* @param integer $size 字号
* @param string $color 文字颜色
* @param integer $locate 文字写入位置
* @param integer $offset 文字相对当前位置的偏移量
* @param integer $angle 文字倾斜角度
* @return Object 当前图片处理库对象
*/
public function text($text, $font, $size, $color = '#00000000',
$locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){
$this->img->text($text, $font, $size, $color, $locate, $offset, $angle);
return $this;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: Input.class.php 2528 2012-01-03 14:58:50Z liu21st $
/** 输入数据管理类
* 使用方法
* $Input = Input::getInstance();
* $Input->get('name','md5','0');
* $Input->session('memberId','','0');
*
* 下面总结了一些常用的数据处理方法。以下方法无需考虑magic_quotes_gpc的设置。
*
* 获取数据:
* 如果从$_POST或者$_GET中获取,使用Input::getVar($_POST['field']);,从数据库或者文件就不需要了。
* 或者直接使用 Input::magicQuotes来消除所有的magic_quotes_gpc转义。
*
* 存储过程:
* 经过Input::getVar($_POST['field'])获得的数据,就是干净的数据,可以直接保存。
* 如果要过滤危险的html,可以使用 $html = Input::safeHtml($data);
*
* 页面显示:
* 纯文本显示在网页中,如文章标题<title>$data</title>: $data = Input::forShow($field);
* HTML 在网页中显示,如文章内容:无需处理。
* 在网页中以源代码方式显示html:$vo = Input::forShow($html);
* 纯文本或者HTML在textarea中进行编辑: $vo = Input::forTarea($value);
* html在标签中使用,如<input value="数据" /> ,使用 $vo = Input::forTag($value); 或者 $vo = Input::hsc($value);
*
* 特殊使用情况:
* 字符串要在数据库进行搜索: $data = Input::forSearch($field);
*/
class Input {
private $filter = null; // 输入过滤
private static $_input = array('get','post','request','env','server','cookie','session','globals','config','lang','call');
//html标签设置
public static $htmlTags = array(
'allow' => 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a',
'ban' => 'html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml',
);
static public function getInstance() {
return get_instance_of(__CLASS__);
}
/**
+----------------------------------------------------------
* 魔术方法 有不存在的操作的时候执行
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $type 输入数据类型
* @param array $args 参数 array(key,filter,default)
+----------------------------------------------------------
* @return mixed
+----------------------------------------------------------
*/
public function __call($type,$args=array()) {
$type = strtolower(trim($type));
if(in_array($type,self::$_input,true)) {
switch($type) {
case 'get': $input =& $_GET;break;
case 'post': $input =& $_POST;break;
case 'request': $input =& $_REQUEST;break;
case 'env': $input =& $_ENV;break;
case 'server': $input =& $_SERVER;break;
case 'cookie': $input =& $_COOKIE;break;
case 'session': $input =& $_SESSION;break;
case 'globals': $input =& $GLOBALS;break;
case 'files': $input =& $_FILES;break;
case 'call': $input = 'call';break;
case 'config': $input = C();break;
case 'lang': $input = L();break;
default:return NULL;
}
if('call' === $input) {
// 呼叫其他方式的输入数据
$callback = array_shift($args);
$params = array_shift($args);
$data = call_user_func_array($callback,$params);
if(count($args)===0) {
return $data;
}
$filter = isset($args[0])?$args[0]:$this->filter;
if(!empty($filter)) {
$data = call_user_func_array($filter,$data);
}
}else{
if(0==count($args) || empty($args[0]) ) {
return $input;
}elseif(array_key_exists($args[0],$input)) {
// 系统变量
$data = $input[$args[0]];
$filter = isset($args[1])?$args[1]:$this->filter;
if(!empty($filter)) {
$data = call_user_func_array($filter,$data);
}
}else{
// 不存在指定输入
$data = isset($args[2])?$args[2]:NULL;
}
}
return $data;
}
}
/**
+----------------------------------------------------------
* 设置数据过滤方法
+----------------------------------------------------------
* @access private
+----------------------------------------------------------
* @param mixed $filter 过滤方法
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
public function filter($filter) {
$this->filter = $filter;
return $this;
}
/**
+----------------------------------------------------------
* 字符MagicQuote转义过滤
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
static public function noGPC() {
if ( get_magic_quotes_gpc() ) {
$_POST = stripslashes_deep($_POST);
$_GET = stripslashes_deep($_GET);
$_COOKIE = stripslashes_deep($_COOKIE);
$_REQUEST= stripslashes_deep($_REQUEST);
}
}
/**
+----------------------------------------------------------
* 处理字符串,以便可以正常进行搜索
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function forSearch($string) {
return str_replace( array('%','_'), array('\%','\_'), $string );
}
/**
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function forShow($string) {
return self::nl2Br( self::hsc($string) );
}
/**
+----------------------------------------------------------
* 处理纯文本数据,以便在textarea标签中显示
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function forTarea($string) {
return str_ireplace(array('<textarea>','</textarea>'), array('&lt;textarea>','&lt;/textarea>'), $string);
}
/**
+----------------------------------------------------------
* 将数据中的单引号和双引号进行转义
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $text 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function forTag($string) {
return str_replace(array('"',"'"), array('&quot;','&#039;'), $string);
}
/**
+----------------------------------------------------------
* 转换文字中的超链接为可点击连接
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function makeLink($string) {
$validChars = "a-z0-9\/\-_+=.~!%@?#&;:$\|";
$patterns = array(
"/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$validChars}]+)/ei",
"/(^|[^]_a-z0-9-=\"'\/])www\.([a-z0-9\-]+)\.([{$validChars}]+)/ei",
"/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$validChars}]+)/ei",
"/(^|[^]_a-z0-9-=\"'\/:\.])([a-z0-9\-_\.]+?)@([{$validChars}]+)/ei");
$replacements = array(
"'\\1<a href=\"\\2://\\3\" title=\"\\2://\\3\" rel=\"external\">\\2://'.Input::truncate( '\\3' ).'</a>'",
"'\\1<a href=\"http://www.\\2.\\3\" title=\"www.\\2.\\3\" rel=\"external\">'.Input::truncate( 'www.\\2.\\3' ).'</a>'",
"'\\1<a href=\"ftp://ftp.\\2.\\3\" title=\"ftp.\\2.\\3\" rel=\"external\">'.Input::truncate( 'ftp.\\2.\\3' ).'</a>'",
"'\\1<a href=\"mailto:\\2@\\3\" title=\"\\2@\\3\">'.Input::truncate( '\\2@\\3' ).'</a>'");
return preg_replace($patterns, $replacements, $string);
}
/**
+----------------------------------------------------------
* 缩略显示字符串
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
* @param int $length 缩略之后的长度
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function truncate($string, $length = '50') {
if ( empty($string) || empty($length) || strlen($string) < $length ) return $string;
$len = floor( $length / 2 );
$ret = substr($string, 0, $len) . " ... ". substr($string, 5 - $len);
return $ret;
}
/**
+----------------------------------------------------------
* 把换行转换为<br />标签
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function nl2Br($string) {
return preg_replace("/(\015\012)|(\015)|(\012)/", "<br />", $string);
}
/**
+----------------------------------------------------------
* 如果 magic_quotes_gpc 为关闭状态,这个函数可以转义字符串
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function addSlashes($string) {
if (!get_magic_quotes_gpc()) {
$string = addslashes($string);
}
return $string;
}
/**
+----------------------------------------------------------
* 从$_POST,$_GET,$_COOKIE,$_REQUEST等数组中获得数据
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function getVar($string) {
return Input::stripSlashes($string);
}
/**
+----------------------------------------------------------
* 如果 magic_quotes_gpc 为开启状态,这个函数可以反转义字符串
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function stripSlashes($string) {
if (get_magic_quotes_gpc()) {
$string = stripslashes($string);
}
return $string;
}
/**
+----------------------------------------------------------
* 用于在textbox表单中显示html代码
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static function hsc($string) {
return preg_replace(array("/&amp;/i", "/&nbsp;/i"), array('&', '&amp;nbsp;'), htmlspecialchars($string, ENT_QUOTES));
}
/**
+----------------------------------------------------------
* 是hsc()方法的逆操作
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $text 要处理的字符串
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static function undoHsc($text) {
return preg_replace(array("/&gt;/i", "/&lt;/i", "/&quot;/i", "/&#039;/i", '/&amp;nbsp;/i'), array(">", "<", "\"", "'", "&nbsp;"), $text);
}
/**
+----------------------------------------------------------
* 输出安全的html,用于过滤危险代码
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $text 要处理的字符串
* @param mixed $allowTags 允许的标签列表,如 table|td|th|td
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function safeHtml($text, $allowTags = null) {
$text = trim($text);
//完全过滤注释
$text = preg_replace('/<!--?.*-->/','',$text);
//完全过滤动态代码
$text = preg_replace('/<\?|\?'.'>/','',$text);
//完全过滤js
$text = preg_replace('/<script?.*\/script>/','',$text);
$text = str_replace('[','&#091;',$text);
$text = str_replace(']','&#093;',$text);
$text = str_replace('|','&#124;',$text);
//过滤换行符
$text = preg_replace('/\r?\n/','',$text);
//br
$text = preg_replace('/<br(\s\/)?'.'>/i','[br]',$text);
$text = preg_replace('/(\[br\]\s*){10,}/i','[br]',$text);
//过滤危险的属性,如:过滤on事件lang js
while(preg_match('/(<[^><]+)(lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){
$text=str_replace($mat[0],$mat[1],$text);
}
while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
$text=str_replace($mat[0],$mat[1].$mat[3],$text);
}
if( empty($allowTags) ) { $allowTags = self::$htmlTags['allow']; }
//允许的HTML标签
$text = preg_replace('/<('.$allowTags.')( [^><\[\]]*)>/i','[\1\2]',$text);
//过滤多余html
if ( empty($banTag) ) { $banTag = self::$htmlTags['ban']; }
$text = preg_replace('/<\/?('.$banTag.')[^><]*>/i','',$text);
//过滤合法的html标签
while(preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i',$text,$mat)){
$text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text);
}
//转换引号
while(preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i',$text,$mat)){
$text=str_replace($mat[0],$mat[1].'|'.$mat[3].'|'.$mat[4],$text);
}
//空属性转换
$text = str_replace('\'\'','||',$text);
$text = str_replace('""','||',$text);
//过滤错误的单个引号
while(preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i',$text,$mat)){
$text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text);
}
//转换其它所有不合法的 < >
$text = str_replace('<','&lt;',$text);
$text = str_replace('>','&gt;',$text);
$text = str_replace('"','&quot;',$text);
//反转换
$text = str_replace('[','<',$text);
$text = str_replace(']','>',$text);
$text = str_replace('|','"',$text);
//过滤多余空格
$text = str_replace(' ',' ',$text);
return $text;
}
/**
+----------------------------------------------------------
* 删除html标签,得到纯文本。可以处理嵌套的标签
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的html
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function deleteHtmlTags($string) {
while(strstr($string, '>')) {
$currentBeg = strpos($string, '<');
$currentEnd = strpos($string, '>');
$tmpStringBeg = @substr($string, 0, $currentBeg);
$tmpStringEnd = @substr($string, $currentEnd + 1, strlen($string));
$string = $tmpStringBeg.$tmpStringEnd;
}
return $string;
}
/**
+----------------------------------------------------------
* 处理文本中的换行
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $string 要处理的字符串
* @param mixed $br 对换行的处理,
* false:去除换行;true:保留原样;string:替换成string
+----------------------------------------------------------
* @return string
+----------------------------------------------------------
*/
static public function nl2($string, $br = '<br />') {
if ($br == false) {
$string = preg_replace("/(\015\012)|(\015)|(\012)/", '', $string);
} elseif ($br != true){
$string = preg_replace("/(\015\012)|(\015)|(\012)/", $br, $string);
}
return $string;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// | lanfengye <zibin_5257@163.com>
// +----------------------------------------------------------------------
class Page {
// 分页栏每页显示的页数
public $rollPage = 5;
// 页数跳转时要带的参数
public $parameter ;
// 分页URL地址
public $url = '';
// 默认列表每页显示行数
public $listRows = 20;
// 起始行数
public $firstRow ;
// 分页总页面数
protected $totalPages ;
// 总行数
protected $totalRows ;
// 当前页数
protected $nowPage ;
// 分页的栏的总页数
protected $coolPages ;
// 分页显示定制
protected $config = array('header'=>'条记录','prev'=>'上一页','next'=>'下一页','first'=>'第一页','last'=>'最后一页','theme'=>' %totalRow% %header% %nowPage%/%totalPage% 页 %upPage% %downPage% %first% %prePage% %linkPage% %nextPage% %end%');
// 默认分页变量名
protected $varPage;
/**
* 架构函数
* @access public
* @param array $totalRows 总的记录数
* @param array $listRows 每页显示记录数
* @param array $parameter 分页跳转的参数
*/
public function __construct($totalRows,$listRows='',$parameter='',$url='') {
$this->totalRows = $totalRows;
$this->parameter = $parameter;
$this->varPage = C('VAR_PAGE') ? C('VAR_PAGE') : 'p' ;
if(!empty($listRows)) {
$this->listRows = intval($listRows);
}
$this->totalPages = ceil($this->totalRows/$this->listRows); //总页数
$this->coolPages = ceil($this->totalPages/$this->rollPage);
$this->nowPage = !empty($_GET[$this->varPage])?intval($_GET[$this->varPage]):1;
if($this->nowPage<1){
$this->nowPage = 1;
}elseif(!empty($this->totalPages) && $this->nowPage>$this->totalPages) {
$this->nowPage = $this->totalPages;
}
$this->firstRow = $this->listRows*($this->nowPage-1);
if(!empty($url)) $this->url = $url;
}
public function setConfig($name,$value) {
if(isset($this->config[$name])) {
$this->config[$name] = $value;
}
}
/**
* 分页显示输出
* @access public
*/
public function show() {
if(0 == $this->totalRows) return '';
$p = $this->varPage;
$nowCoolPage = ceil($this->nowPage/$this->rollPage);
// 分析分页参数
if($this->url){
$depr = C('URL_PATHINFO_DEPR');
$url = rtrim(U('/'.$this->url,'',false),$depr).$depr.'__PAGE__';
}else{
if($this->parameter && is_string($this->parameter)) {
parse_str($this->parameter,$parameter);
}elseif(is_array($this->parameter)){
$parameter = $this->parameter;
}elseif(empty($this->parameter)){
unset($_GET[C('VAR_URL_PARAMS')]);
$var = !empty($_POST)?$_POST:$_GET;
if(empty($var)) {
$parameter = array();
}else{
$parameter = $var;
}
}
$parameter[$p] = '__PAGE__';
$url = U('',$parameter);
}
//上下翻页字符串
$upRow = $this->nowPage-1;
$downRow = $this->nowPage+1;
if ($upRow>0){
$upPage = "<a href='".str_replace('__PAGE__',$upRow,$url)."'>".$this->config['prev']."</a>";
}else{
$upPage = '';
}
if ($downRow <= $this->totalPages){
$downPage = "<a href='".str_replace('__PAGE__',$downRow,$url)."'>".$this->config['next']."</a>";
}else{
$downPage = '';
}
// << < > >>
if($nowCoolPage == 1){
$theFirst = '';
$prePage = '';
}else{
$preRow = $this->nowPage-$this->rollPage;
$prePage = "<a href='".str_replace('__PAGE__',$preRow,$url)."' >上".$this->rollPage."页</a>";
$theFirst = "<a href='".str_replace('__PAGE__',1,$url)."' >".$this->config['first']."</a>";
}
if($nowCoolPage == $this->coolPages){
$nextPage = '';
$theEnd = '';
}else{
$nextRow = $this->nowPage+$this->rollPage;
$theEndRow = $this->totalPages;
$nextPage = "<a href='".str_replace('__PAGE__',$nextRow,$url)."' >下".$this->rollPage."页</a>";
$theEnd = "<a href='".str_replace('__PAGE__',$theEndRow,$url)."' >".$this->config['last']."</a>";
}
// 1 2 3 4 5
$linkPage = "";
for($i=1;$i<=$this->rollPage;$i++){
$page = ($nowCoolPage-1)*$this->rollPage+$i;
if($page!=$this->nowPage){
if($page<=$this->totalPages){
$linkPage .= "<a href='".str_replace('__PAGE__',$page,$url)."'>".$page."</a>";
}else{
break;
}
}else{
if($this->totalPages != 1){
$linkPage .= "<span class='current'>".$page."</span>";
}
}
}
$pageStr = str_replace(
array('%header%','%nowPage%','%totalRow%','%totalPage%','%upPage%','%downPage%','%first%','%prePage%','%linkPage%','%nextPage%','%end%'),
array($this->config['header'],$this->nowPage,$this->totalRows,$this->totalPages,$upPage,$downPage,$theFirst,$prePage,$linkPage,$nextPage,$theEnd),$this->config['theme']);
return $pageStr;
}
}
View raw

(Sorry about that, but we can’t show files that are this big right now.)

This file has been truncated, but you can view the full file.
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: RBAC.class.php 2947 2012-05-13 15:57:48Z liu21st@gmail.com $
/**
+------------------------------------------------------------------------------
* 基于角色的数据库方式验证类
+------------------------------------------------------------------------------
* @category ORG
* @package ORG
* @subpackage Util
* @author liu21st <liu21st@gmail.com>
* @version $Id: RBAC.class.php 2947 2012-05-13 15:57:48Z liu21st@gmail.com $
+------------------------------------------------------------------------------
*/
// 配置文件增加设置
// USER_AUTH_ON 是否需要认证
// USER_AUTH_TYPE 认证类型
// USER_AUTH_KEY 认证识别号
// REQUIRE_AUTH_MODULE 需要认证模块
// NOT_AUTH_MODULE 无需认证模块
// USER_AUTH_GATEWAY 认证网关
// RBAC_DB_DSN 数据库连接DSN
// RBAC_ROLE_TABLE 角色表名称
// RBAC_USER_TABLE 用户表名称
// RBAC_ACCESS_TABLE 权限表名称
// RBAC_NODE_TABLE 节点表名称
/*
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS `think_access` (
`role_id` smallint(6) unsigned NOT NULL,
`node_id` smallint(6) unsigned NOT NULL,
`level` tinyint(1) NOT NULL,
`module` varchar(50) DEFAULT NULL,
KEY `groupId` (`role_id`),
KEY `nodeId` (`node_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `think_node` (
`id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`title` varchar(50) DEFAULT NULL,
`status` tinyint(1) DEFAULT '0',
`remark` varchar(255) DEFAULT NULL,
`sort` smallint(6) unsigned DEFAULT NULL,
`pid` smallint(6) unsigned NOT NULL,
`level` tinyint(1) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `level` (`level`),
KEY `pid` (`pid`),
KEY `status` (`status`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `think_role` (
`id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`pid` smallint(6) DEFAULT NULL,
`status` tinyint(1) unsigned DEFAULT NULL,
`remark` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `pid` (`pid`),
KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `think_role_user` (
`role_id` mediumint(9) unsigned DEFAULT NULL,
`user_id` char(32) DEFAULT NULL,
KEY `group_id` (`role_id`),
KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
*/
class RBAC {
// 认证方法
static public function authenticate($map,$model='') {
if(empty($model)) $model = C('USER_AUTH_MODEL');
//使用给定的Map进行认证
return M($model)->where($map)->find();
}
//用于检测用户权限的方法,并保存到Session中
static function saveAccessList($authId=null) {
if(null===$authId) $authId = $_SESSION[C('USER_AUTH_KEY')];
// 如果使用普通权限模式,保存当前用户的访问权限列表
// 对管理员开发所有权限
if(C('USER_AUTH_TYPE') !=2 && !$_S
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment