Commit fa3f1313 authored by 章建武's avatar 章建武

dep

parent ff0fbc44
vendor
/gatewayworker/vendor
/gatewayworker/linux_vendor
/gatewayworker/stdout.log
/gatewayworker/workerman.log
/runtime/*
/appwww/Uploads/*
/appwww/web
/appwww/api
/Application/Common/Conf/officeConfig/*
.project
.buildpath
.settings
.svn
*.bat
*.iml
.idea
*.log
/AppServer/node_modules
/AppServer/public/hot
/AppServer/public/storage
/AppServer/storage/*.key
/AppServer/vendor
/AppServer/.idea
/AppServer/.vscode
/AppServer/.vagrant
/AppServer/Homestead.json
/AppServer/Homestead.yaml
/AppServer/npm-debug.log
/AppServer/yarn-error.log
/AppServer/.env
/Application/Common/Conf/debugConfig/debug_base.php
\ No newline at end of file
<?php
return array(
'URL_MODEL' => 1, // pathinfo模式,规范化app接口
'MODULE_DENY_LIST' => array('Common'),//禁止访问
'MODULE_ALLOW_LIST' => array('Api'),//允许访问模块
'DEFAULT_MODULE' => 'Api',//默认访问模块
'DEFAULT_CONTROLLER' => 'Index', // 默认控制器名称
'DEFAULT_ACTION' => 'index', // 默认操作名称
);
\ No newline at end of file
\ No newline at end of file
<?php
namespace Api\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
echo 'ok';
}
}
\ No newline at end of file
<?php
namespace Base;
use Think\Auth;
use Admin\Model\AdminModel;
class AdminBaseController extends BaseController{
/**
* 当前登录管理员的ID
* @var int
*/
protected $_back_id;
/**
* 是否是最高管理员
* @var int
*/
protected $_is_top_manager;
protected $baseModel = null;
/**
* 管理员信息数组
* @var array
*/
protected $_admin;
protected function _initialize()
{
$this->baseModel = M();
$this->_back_id = session('back_id');
//登录
if(!$this->_back_id || $this->_back_id < 1){
$this->redirect('Login/login');
}
// id是1的人是最高管理员
if ($this->_back_id == 1) $this->_is_top_manager = 1;
// 查询管理员信息
$this->_admin = (new AdminModel())->where(array('id' => $this->_back_id))->find();
$this->_check_admin();
$this->_menuList();
}
protected function _menuList()
{
//获取登录用户
$this->assign('login_admin',$this->_admin['name']);
//获取用户组菜单
}
/**
* 验证管理员
*/
protected function _check_admin()
{
//超级管理员
if($this->_is_top_manager == 1) return true;
$response = array();
if (empty($this->_admin) || $this->_admin['status'] == 0) {
$this->error('没找到管理员信息或账户被禁用');
}
//验证权限
$auth = new Auth();
if(!$auth->check(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME, $this->_back_id)){
$this->error('对不起,没有权限!');
}
}
//处理get参数
protected function _getParams(){
foreach($_GET as $v){
if(preg_zh_str($v)){
$V = urldecode($v);
}
}
}
}
<?php
namespace Base;
class BaseCacheModel extends AppBaseModel {
protected $_cache_temp = '';
protected $cacheOpt = array();
protected $_returnData = array();
public function _initialize(){
$this->cacheOpt['temp'] = PROJECT_PATH . 'runtime/' . $this->_cache_temp;
$this->cacheOpt['expire'] = 86400*14;
}
/**
* 获取缓存实例
* @param unknown $arr
* @return object
*/
protected function getCacheInstance($arr=array()){
$opt = array_merge($this->cacheOpt,$arr);
return S($opt);
}
/**
* 缓存find查找
* @param unknown $options
* @return array
*/
public function cacheFind($options=array()){
$c = $this->getCacheInstance();
$options = $this->_parseOptions($options);
$cache = $options['cache'];
$options['method'] = 'find';
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
if(!$c->get($key)){
unset($options['alias']);
$c->set($key,$this->find($options));
}
return $c->get($key);
}
/**
* 缓存select查找
* @param unknown $options
* @return array
*/
public function cacheSelect($options=array()){
$c = $this->getCacheInstance();
$options = $this->_parseOptions($options);
$cache = $options['cache'];
$options['method'] = 'select';
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
if(!$c->get($key)){
unset($options['alias']);
$c->set($key,$this->select($options));
}
return $c->get($key);
}
/**
* 缓存Count计数
* @param unknown $options
* @return array
*/
public function cacheCount($field=null){
$c = $this->getCacheInstance();
$options['field'] = $field;
$options = $this->_parseOptions($options);
$cache = $options['cache'];
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
if(!$c->get($key)){
unset($options['alias']);
$this->options = $options;
$c->set($key,$this->count($field));
}
return $c->get($key);
}
/**
* 清除缓存
*/
public function cacheClear(){
$c = $this->getCacheInstance();
return $c->clear();
}
public function getTargetInfo($map){
$info = $this->where($map)->cacheFind();
return $info;
}
/**
* 获取数据返回(带分页)缓存24小时
* @param array $map
* @param number $pageopt
* @return mixed
*/
public function getList($map=array(),$limit=20,$page,$field='') {
// $page = intval($this->postJson['page']);
// $page = $page <= 0 ? 1 : $page;
$map = array_merge($map,array('status'=>0));
if(is_null($limit)) {
$data = $this->where($map)->order($this->getPk().' desc')->cacheSelect();
}else{
$data['count'] = $this->where($map)->cacheCount();
$data['data'] = $this->where($map)->order($this->getPk().' desc')->limit($limit)->field($field)->page($page)->cacheSelect();
$data['pager'] = $this->_pager($page, ceil($data['count']/$limit));
}
return $data;
}
}
\ No newline at end of file
<?php
namespace Base;
use Think\Controller;
use Think\Auth;
class BaseController extends Controller{
public function __construct(){
parent::__construct();
// tettt
}
/**
* 页码信息
* @param unknown $curr_page
* @param unknown $total_page
*/
protected function _pager($curr_page, $total_page){
$pager = array(
'current_page' => $curr_page <= 0 ? 1 : $curr_page,
'last_page' => $curr_page - 1 <=0 ? '' : $curr_page - 1,
'next_page' => ($curr_page + 1 > $total_page) ? '' : $curr_page + 1,
'total_pages' => $total_page,
);
return $pager;
}
protected function _empty(){
if(IS_POST){
$this->apiReturn(404);
}else{
$this->error($response['msg']);
}
}
/**
* 验证管理员
*/
protected function _check_admin()
{
$response = array();
if (empty($this->_admin) || $this->_admin['status'] == 0) {
$response =401;
}
if (empty($response)) {
//验证权限
$auth = new Auth();
if(!$auth->check(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME, $this->_back_id)){
$response = 402;
}
}
if (!empty($response)) {
//ajax请求
if(IS_POST){
$this->apiReturn($response);
}else{
$this->error($response['msg']);
}
}
}
// /**
// * 验证管理员
// */
// protected function _check_admin()
// {
// $response = array();
// if (empty($this->_admin) || $this->_admin['status'] == 0) {
// $this->error('没找到管理员信息或账户被禁用');
// }
// //验证权限
// $auth = new Auth();
// if(!$auth->check(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME, $this->_back_id)){
// $this->error('对不起,没有权限!');
// }
// }
/**
* 设置事务标识
* @param unknown $rst
* @param unknown $is_commit
* @return boolean
*/
protected function _setCommit($rst, $is_commit){
return $rst && $is_commit;
}
/**
* 开始事务
*/
protected function _trans(){
$this->baseModel->startTrans();
return true;
}
/**
* 事务提交或回滚
* @param unknown $is_commit
*/
protected function _commitOrRollback($is_commit){
if($is_commit){
return $this->_commit();
}else{
$this->_rollback();
return false;
}
}
/**
* 提交事务
*/
protected function _commit(){
return $this->baseModel->commit();
}
/**
* 回滚事务
*/
protected function _rollback(){
$this->baseModel->rollback();
return false; // 添加数据失败
}
}
\ No newline at end of file
<?php
/**
* 判断字符串是否包含中文
* @param unknown $zh_cn csj
* @return unknown
*/
function preg_zh_str($str){
if(preg_match("/[\x7f-\xff]/",$str)){
return true;
}else{
return false;
}
}
/**
* 匹配中文
* @param unknown $zh_cn
* @return unknown
*/
function preg_zh($zh_cn){
preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$zh_cn, $result);
return $result;
}
/**
* 匹配银行卡号
* @param unknown $bank_account
* @return unknown
*/
function preg_bank_account($bank_account){
$card = $bank_account;
if (!is_numeric($card))
return false;
$card_len = strlen($card);
$i = 0;
$num_i = array();
do{
if (!$i){
$num_x = $card_len % 2 ? 1 : 2;
} else {
$num_x = $num_x == 1 ? 2 : 1;
}
$num_i[$i] = (int)$card[$i] * $num_x;
$num_i[$i] = $num_i[$i] > 9 ? $num_i[$i] - 9 : $num_i[$i];
}while(isset($card[++$i]));
$num_sum = array_sum($num_i);
return $num_sum % 10 ? false : true;
}
/**
* 匹配数字
* @param unknown $number
* @return unknown
*/
function preg_number($number){
preg_match("/^[0-9]*$/", $number, $result);
return $result;
}
/**
匹配手机号码
规则:
手机号码基本格式:
前面三位为:
移动:134-139 147 150-152 157-159 182 187 188
联通:130-132 155-156 185 186
电信:133 153 180 189
后面八位为:
0-9位的数字
*/
function preg_phone($phone_num){
// $rule = "/^((13[0-9])|147|(15[0-35-9])|180|182|177|(18[5-9]))[0-9]{8}$/A";
$rule = '#^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^17[0,1,3,6,7,8]{1}\d{8}$|^18[\d]{9}$#';
preg_match($rule,$phone_num,$result);
return $result;
}
/**
匹配身份证号
规则:
15位纯数字或者18位纯数字或者17位数字加一位x
*/
function preg_id_card($id_card_no){
return verify_user_idcard_no($id_card_no);
}
function preg_email($email){
// $rule ="/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$/";
// preg_match($rule,$email,$result);
// return $result;
$result = filter_var($email, FILTER_VALIDATE_EMAIL);
return $result;
}
/**
* 验证用户身份证是否合法
* @param unknown $id_card_no 身份证号
* @return boolean
*/
function verify_user_idcard_no($id_card_no){
$id_card_no = strtoupper($id_card_no);
$rule = '/^(([0-9]{18})|([0-9]{17}X))$/';
preg_match($rule,$id_card_no, $result);
if(!$result)
return false;
$weight = array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2); // 十七位数字
$validate = array('1','0','X','9','8','7','6','5','4','3','2'); // mod11,对应校验码字符值
$sum = 0;
$last_id = substr($id_card_no, 17);
for($i = 0; $i < 17; $i++){
$id = $id_card_no{$i};
$sum += $id * $weight[$i];
}
$val = $validate[$sum%11];
return $last_id == $val;
}
/**
* 匹配身份证的性别,0-未知,1-女,2-男
* @param unknown $id_card_no
* @return number
*/
function preg_id_card_sex($id_card_no){
$sex = 0;
if(!preg_id_card($id_card_no)) return $sex;
$num = substr($id_card_no, 16,1);
if($num % 2 == 0){
$sex = 1; // 偶-女 奇-男
}else{
$sex = 2;
}
return $sex;
}
<?php
function get_ip(){
static $realip;
if (isset($_SERVER)){
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
$realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
$realip = $_SERVER["HTTP_CLIENT_IP"];
} else {
$realip = $_SERVER["REMOTE_ADDR"];
}
}else {
if (getenv("HTTP_X_FORWARDED_FOR")){
$realip = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("HTTP_CLIENT_IP")) {
$realip = getenv("HTTP_CLIENT_IP");
} else {
$realip = getenv("REMOTE_ADDR");
}
}
return $realip;
}
/**
* 图片全路径
* @param string $pic_path 数据库的路径
* @param string param 路径参数
* @param string which_cdn 采用那个cdn
* @return string 返回文件路径
* @author nk
*/
function pic_path($pic_path, $param = '', $which_cdn = 'qiniu'){
$cdn_path = '';
if(C('IS_USE_CDN')){
switch ($which_cdn){
case 'qiniu':
$cdn_path = qiniu_cdn_path($pic_path, $param);
break;
}
// 如果cdn 路径存在,即返回cdn路径
if($cdn_path) return $cdn_path;
}
if(strpos($pic_path,'http://') === 0 || strpos($pic_path,'https://') === 0)
return $pic_path;
$domain = C('PIC_DOMAIN');
$pic_path = ltrim(str_replace('\\', '/', $pic_path),'/');
if($pic_path)
return $domain.$pic_path;
return '';
}
/**
* 递归创建文件夹
* @param unknown $dir
* @return boolean
*/
function mkdirs($dir){
return is_dir($dir) or (mkdirs(dirname($dir)) and mkdir($dir, 0777));
}
/**
* [uploadActions 上传图片]
* @param [type] $name [图片原名字]
* @param [type] $file_type [图片类型 goods/user/comment/theme/banner/city]
* @param string $value_id [类型ID]
* @param string $filename [单文件上传]
* @param string $filesize [限制大小]
* @return [type] [array(array('file_name'=>'name','pic_path'=>'path'))]
* @author [完颜不破] <[email address]>
*/
function uploadAction($name,$file_type,$value_id='',$filename='',$filesize='31457280') {
if(!$value_id){
return false;
}
$date = date('Ym',time());
$date_path = './Uploads/'.$date.'/';
$rootPath =$date_path.$file_type.'/'.$value_id.'/';
mkdirs(rtrim($rootPath));
$config = array(
'maxSize'=>$filesize,
'rootPath'=>$rootPath,
'savePath'=>'',
'saveName'=>array('uniqid',''),
'exts'=>array('jpg', 'gif', 'png', 'jpeg','chm','pdf','zip','rar','tar','gz','bzip2'),
'autoSub'=>true,
'subName'=>false,
);
$upload =new \Think\Upload($config,'Local');
if($filename){
$info = $upload->upload_ad($filename);
}else{
$info = $upload->upload();
}
if(!$info){
// return $upload->getError();
return false;
}else{
foreach($info as $key=>$file){
$file_path = $config['rootPath'].$file['savepath'].$file['savename'];
$file_path = ltrim($file_path,'./');
$path_arr[$key]['file_name'] = $name[$key];
$path_arr[$key]['pic_path'] = $file_path;
$path_arr[$key]['sort'] = $key+1;
}
return $path_arr;
}
}
//excel导入图片方法
function getExtendFileName($file_name) {
$extend = pathinfo($file_name);
$extend = strtolower($extend["extension"]);
return $extend;
}
function extractImageFromWorksheet($worksheet,$basePath){
$result = array();
$imageFileName = "";
foreach ($worksheet->getDrawingCollection() as $drawing) {
$xy=$drawing->getCoordinates();
$path = $basePath;
// for xlsx
if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
$filename = $drawing->getPath();
$imageFileName = $drawing->getIndexedFilename();
$path = $path . $drawing->getIndexedFilename();
copy($filename, $path);
$result[$xy] = $path;
// for xls
} else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {
$image = $drawing->getImageResource();
$renderingFunction = $drawing->getRenderingFunction();
switch ($renderingFunction) {
case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG:
$imageFileName = $drawing->getIndexedFilename();
$path = $path . $drawing->getIndexedFilename();
imagejpeg($image, $path);
break;
case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF:
$imageFileName = $drawing->getIndexedFilename();
$path = $path . $drawing->getIndexedFilename();
imagegif($image, $path);
break;
case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG:
$imageFileName = $drawing->getIndexedFilename();
$path = $path . $drawing->getIndexedFilename();
imagegif($image, $path);
break;
case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT:
$imageFileName = $drawing->getIndexedFilename();
$path = $path . $drawing->getIndexedFilename();
imagegif($image, $path);
break;
}
$result[$xy] = $imageFileName;
}
}
return $result;
}
function add_water($path,$type=1,$width=0,$location=9){
switch ($type) {
case '1':
$image = new \Think\Image();
$water_path = $image->open($path)->water(C('WATER_LOGO'),$location,50)->save($path);
return $water_path;
break;
case '2':
$arr_path = explode('/',$path);
array_pop($arr_path);
$savepath = implode('/',$arr_path);
$name = uniqid();
$image->open($path);
$type = $image->type();
$thumb_path = $image->thumb($width, $width,\Think\Image::IMAGE_THUMB_SCALE)->save($savepath.'/suo'.$name.'.'.$type);
return $thumb_path;
break;
case '3':
$image = new \Think\Image();
$water_path = $image->open($path)->water(C('WATER_LOGO'),$location,50)->save($path);
$arr_path = explode('/',$path);
array_pop($arr_path);
$savepath = implode('/',$arr_path);
$name = uniqid();
$image->open($path);
$type = $image->type();
$thumb_path =$savepath.'/suo'.$name.'.'.$type;
$res = $image->thumb($width, $width,\Think\Image::IMAGE_THUMB_SCALE)->save($thumb_path);
return array('water'=>$water_path,'thumb'=>$thumb_path);
break;
default:
# code...
break;
}
}
\ No newline at end of file
\ No newline at end of file
<?php
return array(
//'配置项'=>'配置值'
);
\ No newline at end of file
<?php
return array(
//加载配置项
'LOAD_EXT_CONFIG' => array(
'debugConfig/conf_base',
'debugConfig/conf_db',
'debugConfig/conf_email',
'debugConfig/conf_cache',
'debugConfig/conf_upload',
'debugConfig/conf_safety',
'debugConfig/conf_cdn',
'status_code',
),
'LOAD_EXT_FILE' => 'func_preg,func_third,func_log,func_app_common',
);
\ No newline at end of file
<?php
return array(
'DEFAULT_FILTER' => 'addslashes',
'IS_DEBUG_VER' => true,
'URL_CASE_INSENSITIVE' =>false,
'DOMAIN' => 'http://mallapp.guoguodz.com/',
'WEI_DOMAIN' => 'https://vote.guoguodz.com/',
'APP_NAME' => '时尚天河',
// 服务号授权ID和secret
'APPID' => 'wx6e539bffabd650fd',
'APP_SECRET' => '54f57c5d48319eeda2a37cbcefaf9644',
);
<?php
return array(
// 开放memcached
'IS_OPEN_MEMCACHED' => true,
'MEMCACHED_HOST' => '127.0.0.1',
'MEMCACHED_PORT' => '11211',
'IS_OPEN_REDIS' => true, // 开启redis
'CACHE_REDIS' => array(
'type' => 'redis',
'host' => '127.0.0.1',
'port' => '6379',
'prefix' => 'redis_',
'expire' => 7200,
// 'timeout'=> 1,
),
'REDIS_AUTH' => '',
);
\ No newline at end of file
<?php
return array(
'DB_TYPE' => 'mysqli', // 数据库类型
'DB_HOST' => '192.168.6.219', // 服务器地址
'DB_NAME' => 'wei_mall', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => 'uORO!$rFw5Bj^wSG', // 密码
'DB_PORT' => '3306', // 端口
'DB_PREFIX' => 'mall_', // 数据库表前缀
);
\ No newline at end of file
<?php
return array(
// 配置邮件发送服务器
'MAIL_HOST' => '', //smtp服务器的名称
'MAIL_SMTPAUTH' => TRUE, //启用smtp认证
'MAIL_USERNAME' => '', //你的邮箱名
'MAIL_FROM' => '', //发件人地址
'MAIL_FROMNAME' => '', //发件人姓名
'MAIL_PASSWORD' => '', //邮箱密码
'MAIL_CHARSET' => 'utf-8', //设置邮件编码
'MAIL_ISHTML' => TRUE, // 是否HTML格式邮件
'MAIL_PORT' => 25, // 发送邮件端口
'MAIL_SERVICE' => 1, // 开启邮件服务
);
<?php
return array(
'SYS_AUTO_SECRET_KEY' => '7V/s-h<@Lrk+EV1/y&}-sY=4YQZc-v!O', // 系统加密随机字符串,不能改动
);
\ No newline at end of file
<?php
return array(
/* 图片上传相关配置 */
'PICTURE_UPLOAD' => array(
'mimes' => '', //允许上传的文件MiMe类型
'maxSize' => 2*1024*1024, //上传的文件大小限制 (0-不做限制)
'exts' => 'jpg,gif,png,jpeg', //允许上传的文件后缀
'autoSub' => true, //自动子目录保存文件
'subName' => array('date', 'Y-m-d'), //子目录创建方式,[0]-函数名,[1]-参数,多个参数使用数组
'rootPath' => './Uploads/', //保存根路径
'savePath' => '', //保存路径
'saveName' => array('uniqid', ''), //上传文件命名规则,[0]-函数名,[1]-参数,多个参数使用数组
'saveExt' => '', //文件保存后缀,空则使用原后缀
'replace' => false, //存在同名是否覆盖
'hash' => true, //是否生成hash编码
'callback' => false, //检测文件是否存在回调函数,如果存在返回文件信息数组
),
'UPLOADS_ROOT' => 'Uploads/',
'DEFAULT_AVATAR_PIC' => '', // 默认头像路径
'DEFAULT_BG_PIC' => '', // 默认背景路径
);
\ No newline at end of file
\ No newline at end of file
<?php
return array(
//加载配置项
'LOAD_EXT_CONFIG' => array(
'officeConfig/conf_base',
'officeConfig/conf_db',
'officeConfig/conf_email',
'officeConfig/conf_cache',
'officeConfig/conf_upload',
'officeConfig/conf_safety',
'officeConfig/conf_cdn',
'status_code',
),
'LOAD_EXT_FILE' => 'func_preg,func_third,func_log,func_app_common',
);
\ No newline at end of file
<?php
return array(
'APP_CODE' => array(
'1' => '',
'401'=>'没找到管理员信息或账户被禁用',
'402'=>'对不起,没有权限!',
'404' => '请求路径不存在',
),
);
<?php
namespace Common\Logic\Wechat;
class Curl
{
/**
* curl资源
* @var unknown
*/
protected $ch;
/**
* 配置
* @var array
*/
protected $opt_arr = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => false,
CURLOPT_NOSIGNAL => true
);
/**
* curl_exec函数返回值
* @var array
*/
protected $result;
/**
* curl_getinfo函数返回值
* @var array
*/
protected $curl_info;
public function __construct()
{
$this->_init();
}
/**
* 设置配置信息
* @param int 键
* @param mixed 值
* @return \Common\Logic\Wechat\Curl
*/
public function setOpt($key, $val)
{
$this->opt_arr[$key] = $val;
return $this;
}
/**
* 设置url
* @param string url
* @return \Common\Logic\Wechat\Curl
*/
public function setUrl($url)
{
return $this->setOpt(CURLOPT_URL, $url);
}
/**
* 设置https请求
* @return \Common\Logic\Wechat\Curl
*/
public function setHttps()
{
return $this
->setOpt(CURLOPT_SSL_VERIFYPEER, false)
->setOpt(CURLOPT_SSL_VERIFYHOST, 2);
}
/**
* 初始化
* @throws \Exception
*/
protected function _init()
{
$ch = curl_init();
if (!$ch) throw new \Exception('初始化Curl错误');
$this->ch = $ch;
}
/**
* 设置请求方式为get
* @return \Common\Logic\Wechat\Curl
*/
public function setGet()
{
return $this->setOpt(CURLOPT_POST, false);
}
/**
* 设置请求方式为post
* @return \Common\Logic\Wechat\Curl
*/
public function post()
{
return $this->setOpt(CURLOPT_POST, true);
}
/**
* 发送请求
*/
public function request()
{
curl_setopt_array($this->ch, $this->opt_arr);
// 取得请求结果
$this->result = curl_exec($this->ch);
$error = curl_errno($this->ch);
$this->curl_info = curl_getinfo($this->ch);
if ($error > 0) throw new \Exception('Curl 错误:' . curl_strerror ($error) . '(' . $error . ')');
return $this;
}
public function __get($att)
{
switch ($att) {
case 'result':
case 'curl_info':
return $this->$att;
}
throw new \Exception($att . ' is not fund');
}
}
<?php
namespace Common\Logic\Wechat;
use Think\Log;
/**
* 微信网页接口类
*
* 微信网页开发的接口
*
* @see https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
*/
class WechatWebApi
{
/**
* 网页授权的地址
* @var string
*/
const OAUTH2_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect';
/**
* 网页授权获取access_token的地址
* @var string
*/
const OAUTH2_ACCESS_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code';
/**
* 网页授权后获取用户信息的地址
* @var unknown
*/
const USER_INFO_URL = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN ';
/**
* 获取token的url
* @var string
*/
const TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s';
/**
* 获取js ticket的请求url
* @var string
*/
const JS_TICKET_URL = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi';
/**
* 实例
* @var object
*/
protected static $instance;
/**
* @var string
*/
protected $appId = '';
/**
* @var string
*/
protected $appSecret = '';
/**
* 错误信息
* @var array
*/
protected $error = array();
/**
* __construct
*/
protected function __construct()
{
$this->appId = C('APPID');
$this->appSecret = C('APP_SECRET');
}
/**
* 获取实例
* @return \Common\Logic\Wechat\WechatApi
*/
public static function getInstance()
{
return self::$instance ? self::$instance : self::$instance = new WechatWebApi();
}
public function getAppId()
{
return $this->appId;
}
/**
* 获取js ticket的请求url
* @param string $token
* @return string
*/
public function getJsTicketUrl($token)
{
return sprintf(self::JS_TICKET_URL, $token);
}
/**
* 获取js ticket
* @param string $token
* @return boolean|array
*/
public function getJsTicket($token)
{
$url = $this->getJsTicketUrl($token);
$curl = new Curl();
$rst = $curl->setUrl($url)->setHttps()->request()->result;
$rst_arr = json_decode($rst, true);
if (!is_array($rst_arr) || empty($rst_arr) || !array_key_exists('ticket', $rst_arr)) {
$this->setError('get js ticket error:'.$rst);
return false;
}
return $rst_arr;
}
/**
* 获取token的请求url
* @return string
*/
public function getTokenUrl()
{
return sprintf(self::TOKEN_URL, $this->appId, $this->appSecret);
}
public function getToken()
{
$url = $this->getTokenUrl();
$curl = new Curl();
$rst = $curl->setUrl($url)->setHttps()->request()->result;
$rst_arr = json_decode($rst, true);
if (!is_array($rst_arr) || empty($rst_arr) || !array_key_exists('access_token', $rst_arr)) {
$this->setError('get token error:'.$rst);
return false;
}
return $rst_arr;
}
/**
* 获取授权地址
*
* @param string 授权后返回的url
* @param string $scope
* @param string $state
*
* @return string|boolean 失败返回false否则返回url
*/
public function getOauthUrl($url, $scope = 'snsapi_base', $state = '')
{
if (empty($this->appId)) {
$this->setError('appId is empty');
return false;
}
return sprintf(self::OAUTH2_URL, $this->appId, urlencode($url), $scope, $state);
}
/**
* 获取code换取access_token的地址
*
* @param string 授权后返回的url
* @param string $scope
* @param string $state
*
* @return string|boolean 失败返回false否则返回url
*/
public function getAccessTokenUrl($code)
{
if (empty($this->appId) || empty($this->appSecret)) {
$this->setError('appId or appSecret is empty');
return false;
}
return sprintf(self::OAUTH2_ACCESS_URL, $this->appId, $this->appSecret, $code);
}
/**
* 获取授权access_token
* @param string code
* @return array|boolean 失败返回false,否则返回access_token数组
*/
public function getOauthAccess($code)
{
$url = $this->getAccessTokenUrl($code);
if (!$url) return false;
$curl = new Curl();
$rst = $curl->setUrl($url)->setHttps()->request()->result;
$rst_arr = json_decode($rst, true);
if (!is_array($rst_arr) || empty($rst_arr) || !array_key_exists('access_token', $rst_arr)) {
$this->setError('get access token error:'.$rst);
return false;
}
return $rst_arr;
}
/**
* 获取错误信息
* @return array
*/
public function getError()
{
return $this->error;
}
/**
* 设置错误信息
* @param string $msg
*/
protected function setError($msg)
{
$this->error[] = $msg;
Log::write($msg);
}
/**
* 获取用户信息的地址
* @param string access_token
* @param string openid
* @return boolean|string
*/
public function userInfoUrl($access_token, $openid)
{
if (empty($access_token) || empty($openid)) {
$this->setError('access token or openid is empty');
return false;
}
return sprintf(self::USER_INFO_URL, $access_token, $openid);
}
/**
* 获取用户信息
* @param string access_token
* @param string openid
* @return boolean|array
*/
public function getUserInfo($access_token, $openid)
{
$url = $this->userInfoUrl($access_token, $openid);
if (!$url) return false;
$curl = new Curl();
$rst = $curl->setUrl($url)->setHttps()->request()->result;
$rst_arr = json_decode($rst, true);
if (!is_array($rst_arr) || empty($rst_arr) || !array_key_exists('openid', $rst_arr)) {
$this->setError('get user info error:'.var_export($rst, true));
return false;
}
return $rst_arr;
}
}
\ No newline at end of file
\ No newline at end of file
<?php
return array(
'URL_MODEL' => 1, // pathinfo模式,规范化app接口
'DEFAULT_MODULE' => 'Frontend',//默认访问模块
'DEFAULT_CONTROLLER' => 'Index', // 默认控制器名称
'DEFAULT_ACTION' => 'index', // 默认操作名称
'TMPL_PARSE_STRING' => array (
'__CSS__' => C('DOMAIN').STATIC_COMEON_ASSETS.'/css',
'__JS__' => C('DOMAIN').STATIC_COMEON_ASSETS.'/js',
'__IMGAGES__' => C('DOMAIN').STATIC_COMEON_ASSETS.'/images',
'__IMGTEXT__' => C('DOMAIN').STATIC_COMEON_ASSETS.'/imgtext',
),
);
\ No newline at end of file
\ No newline at end of file
<?php
namespace Frontend\Controller;
use Think\Controller;
use Common\Logic\Wechat\WechatWebApi;
class IndexController extends Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
session_start();
if (!$_SESSION["headimgurl"]) {
redirect('http://mallapp.guoguodz.com/h5_pic/appwww/index.php/WxAuthorize');
return;
}
if($_SERVER['QUERY_STRING']){
$url = '?'.$_SERVER['QUERY_STRING'];
}
$link = 'http://'.$_SERVER["HTTP_HOST"].'/h5_pic/appwww/index.php'.$url;
$this->assign('link',$link);
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$nonceStr = "";
for ($i = 0; $i < 16; $i++) {
$nonceStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
$weChatApi = WechatWebApi::getInstance();
$wxToken = S('wx_token');
if (!$wxToken) {
$_data = $weChatApi->getToken();
if (!$_data) $this->error(var_export($weChatApi->getError(), true));
S('wx_token', $_data['access_token'], 6800);
$wxToken = $_data['access_token'];
}
$jsapi_ticket = S('jsapi_ticket');
if(!$jsapi_ticket){
$_data = $weChatApi->getJsTicket($wxToken);
if (!$_data) $this->error(var_export($weChatApi->getError(), true));
S('jsapi_ticket', $_data['ticket'], 6800);
$jsapi_ticket = $_data['ticket'];
}
$argu = array();
$argu['appId'] = $weChatApi->getAppId();
$argu['url'] = $link;
$argu['nonceStr'] = $nonceStr;
$argu['headimg'] = $_SESSION["headimgurl"];
$argu['wx_name'] = $_SESSION["wx_name"];
$argu['timestamp'] = NOW_TIME;
$wxToken = $wxToken;
$argu['jsapi_ticket'] = $jsapi_ticket;
$string = "jsapi_ticket=".$argu['jsapi_ticket']."&noncestr=".$argu['nonceStr']."&timestamp=".$argu['timestamp']."&url=".$argu['url'];
$argu['signature'] = sha1(trim($string));
$this->assign($argu);
$this->display('index');
}
//上传图片
public function upload (){
$link = 'http://mallapp.guoguodz.com/h5_pic/appwww/';
// $link = 'www.h5_pic.net/';
$mo = I('post.mo'); //mo=1 点击切换生成 mo=2 自由填写
$mtxt = I('post.mtxt');
$txt1 = I('post.txt1');
$txt2 = I('post.txt2');
$txt3 = I('post.txt3');
$txt4 = I('post.txt4');
$sign_pic = I('post.sign_pic');
$pimg = I('post.pimg');
$user = I('post.user');
//主图
$pic_url = $link.$this->get_base64_img($pimg);
// $pic_url = 'http://www.h5_pic.net/H5/pimg/1576225374.png';
//水印图
$mtxt = 'http://mallapp.guoguodz.com/h5_pic/appwww/Assets/Admin/images/m'.$mtxt.'.png';
//logo
$logo = 'http://mallapp.guoguodz.com/h5_pic/appwww/Assets/Admin/images/logo.png';
//二维码
$qr_code = 'http://mallapp.guoguodz.com/h5_pic/appwww/Assets/Admin/images/qr_code.png';
//微信名称
$user_str = 'Via:'.$user;
//指定要缩放到的宽度
$maxW = 640;
//指定要缩放到的高度
$maxH = 1048;
//mo=1 点击切换生成 mo=2 自由填写
$bg = imagecreatetruecolor($maxW, $maxH);
$background = imagecolorallocate($bg, 255, 255, 255);
imagefill($bg,0,0,$background);
$im = imagecreatefromjpeg($pic_url);
// $im = imagecreatefrompng($pic_url);
imagefilter($im,IMG_FILTER_GRAYSCALE);
$oldW = imagesx($im);
$oldH = imagesy($im);
$source_ratio = $oldW / $oldH;
$target_ratio = 1028 / 620;
$source_width = $oldW;
$source_height = $oldH;
if ($source_ratio > $target_ratio){
// image-to-height
$newW = $source_width;
$newH = $source_width * $target_ratio;
}elseif ($source_ratio < $target_ratio){
//image-to-widht
$newW = $source_height / $target_ratio;
$newW = $newW - 30;
$newH = $source_height;
}else{
//image-size-ok
$newW = $source_width;
$newH = $source_height;
}
// //判断那个边比较长,利用较长的边求得比例
// if($oldW>$oldH){
// //求得比例
// $b = $oldW/$maxW;
// //获取缩放之后的宽高
// $newW = $oldW/$b*0.2;
// $newH = $oldH/$b*0.2;
// }else{
// //求得比例
// $b = $oldH/$maxH;
// //获取缩放之后的宽高
// $newW = $oldW/$b*0.2;
// $newH = $oldH/$b*0.2;
//
// }
imagecopyresampled($bg, $im, 10, 10, 0, 0, 620, 1028, $newW, $newH);
if($mo == 1){
$stamp = imagecreatefrompng($mtxt);
$code = imagecreatefrompng($qr_code);
$logo = imagecreatefrompng($logo);
// 利用图像的宽度和水印的外边距计算位置,并且将水印复制到图像上
imagecopymerge($bg, $stamp, 0, 0, 0, 0, 640, 261, 100);
imagecopymerge($bg, $code, 5, 880, 0, 0, 130, 130, 100);
imagecopymerge($bg, $logo, 0, 930, 0, 10, 640, 180, 100);
$text_str = PROJECT_PATH.'appwww/msyh.ttf';
$textcolor = imagecolorallocate($bg, 255, 255, 255);
imagettftext($bg, 24, 0, 10, 298, $textcolor, $text_str, mb_convert_encoding($user_str, "utf-8"));
// 输出图像并释放内存
//header('Content-type: image/png');
}else{
$code = imagecreatefrompng($qr_code);
$logo = imagecreatefrompng($logo);
imagecopymerge($bg, $code, 5, 880, 0, 0, 130, 130, 100);
imagecopymerge($bg, $logo, 0, 930, 0, 10, 640, 180, 100);
$text_str = PROJECT_PATH.'appwww/msyh.ttf';
$textcolor = imagecolorallocate($bg, 255, 255, 255);
$t1 = mb_convert_encoding($txt1, "utf-8");
$t2 = mb_convert_encoding($txt2, "utf-8");
$t3 = mb_convert_encoding($txt3, "utf-8");
$t4 = mb_convert_encoding($txt4, "utf-8");
$rectangle_color = imagecolorallocate($bg, 255, 0, 0);
imagefilledrectangle($bg, 0, 135, strlen($t3)*18.5, 187, $rectangle_color);
imagefilledrectangle($bg, 0, 195, strlen($t4)*18.5, 245, $rectangle_color);
imagettftext($bg, 38, 0, 10, 66, $textcolor, $text_str, mb_convert_encoding($txt1, "utf-8"));
imagettftext($bg, 38, 0, 10, 126, $textcolor, $text_str, mb_convert_encoding($txt2, "utf-8"));
imagettftext($bg, 38, 0, 10, 180, $textcolor, $text_str, mb_convert_encoding($txt3, "utf-8"));
imagettftext($bg, 38, 0, 10, 238, $textcolor, $text_str, mb_convert_encoding($txt4, "utf-8"));
imagettftext($bg, 24, 0, 10, 288, $textcolor, $text_str, mb_convert_encoding($user_str, "utf-8"));
}
$text_c = imagecolorallocate($bg, 255, 255, 255);
imagettftext($bg, 12, 0, 10, 1030, $text_c, $text_str, mb_convert_encoding('识别二维码参与H5互动', "utf-8"));
$path = "H5/pic/";
if (!is_dir($path)){
mkdir($path,0777,true);
}
imagepng($bg,$path.$sign_pic.'.png');
imagedestroy($bg);
//返回处理后的水印图片
$url = 'http://mallapp.guoguodz.com/h5_pic/appwww/H5/pic/'.$sign_pic.'.png';
$data = ['url'=>$url,'msg'=>'ok'];
$this->ajaxReturn($data);
}
//base64转图片
function get_base64_img($base64){
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64, $result)){
$type = $result[2];
$path = "H5/pimg/";
if (!is_dir($path)){
mkdir($path,0777,true);
}
$new_file = $path.time().".{$type}";
$data = file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64)));
if ($data){
return $new_file;
}else{
return false;
}
}
}
}
<?php
namespace Frontend\Controller;
use Think\Controller;
use Common\Logic\Wechat\WechatWebApi;
class WxAuthorizeController extends Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
session_start();
// 授权成功后回到前端的地址
$front_url = urlencode(trim('http://mallapp.guoguodz.com/h5_pic/appwww/index.php'));
if (!$this->checkFrontUrl($front_url)) $this->error('url参数不正确');
// 获取code后返回的地址
$redirect_uri = U('getUserInfo', '', true, true);
$weChatApi = WechatWebApi::getInstance();
$auth_url = $weChatApi->getOauthUrl($redirect_uri, 'snsapi_userinfo');
redirect($auth_url);
}
public function getUserInfo()
{
session_start();
$front_url = 'http://mallapp.guoguodz.com/h5_pic/appwww/index.php';
$code = trim(I('get.code', ''));
if (empty($code)) $this->error('code参数错误');
// 获取access token
$weChatApi = WechatWebApi::getInstance();
$token_data = $weChatApi->getOauthAccess($code);
if (!$token_data) $this->error(var_export($weChatApi->getError(), true));
// 获取微信用户信息
$wei_user = $weChatApi->getUserInfo($token_data['access_token'], $token_data['openid']);
if (!$wei_user) $this->error(var_export($weChatApi->getError(), true));
$_SESSION["headimgurl"]=$wei_user['headimgurl'];
$_SESSION["wx_name"]=$wei_user['nickname'];
$url_query = array('open_id' => $user_info['open_id']);
redirect($front_url);
}
protected function filterNickname($nickname)
{
$tmpStr = json_encode($nickname);
$tmpStr = preg_replace("#(\\\ud[0-9a-f]{3})|(\\\ue[0-9a-f]{3})#ie","",$tmpStr);
$tmpStr = json_decode($tmpStr);
$tmpStr = str_replace('\'', '', $tmpStr);
return trim($tmpStr);
}
/**
* 把数组按照键值对拼进url的query部分
*
* @param string url
* @param array $param
* @return string
*/
protected function parseFrontUrl($url, $param)
{
$front_url = '';
$url_components = parse_url($url);
$front_url .= $url_components['scheme'] . '://' . $url_components['host'];
$front_url .= $url_components['port'] == '80' ? '' : ':' . $url_components['port'];
$front_url .= $url_components['path'];
parse_str($url_components['query'], $query_arr);
$query_arr = $query_arr ? array_merge($query_arr, $param) : $param;
$front_url .= !empty($query_arr) ? '?' . http_build_query($query_arr) : '';
$front_url .= $url_components['fragment'] ? '#' . $url_components['fragment'] : '';
return $front_url;
}
/**
* 检查前端的URL,判断是否非本站
* @param string $url
* @return boolean 正确返回true,否则返回false
*/
protected function checkFrontUrl($url)
{
if (empty($url)) return false;
// @todo **原习斌**
return true;
}
}
This diff is collapsed.
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP 默认的调试模式配置文件
*/
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_DEBUG' => true, // 开启调试模式 记录SQL日志
'TMPL_CACHE_ON' => false, // 是否开启模板编译缓存,设为false则每次都会重新编译
'TMPL_STRIP_SPACE' => false, // 是否去除模板文件里面的html空格与换行
'SHOW_ERROR_MSG' => true, // 显示错误信息
'URL_CASE_INSENSITIVE' => false, // URL区分大小写
);
\ No newline at end of file
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
版权所有Copyright © 2006-2014 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1. 需要给代码的用户一份Apache Licence ;
2. 如果你修改了代码,需要在被修改的文件中说明;
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可,但不可以表现为对Apache Licence构成更改。
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 THE
COPYRIGHT OWNER OR 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.
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP English language package
*/
return array(
/* core language package */
'_MODULE_NOT_EXIST_' => "Module can't be loaded",
'_CONTROLLER_NOT_EXIST_' => "Controller can't be loaded",
'_ERROR_ACTION_' => 'Illegal Action',
'_LANGUAGE_NOT_LOAD_' => "Can't load language package",
'_TEMPLATE_NOT_EXIST_' => "Template doesn't exist",
'_MODULE_' => 'Module',
'_ACTION_' => 'Action',
'_MODEL_NOT_EXIST_' => "Model can't be loaded",
'_VALID_ACCESS_' => 'No access',
'_XML_TAG_ERROR_' => 'XML tag syntax errors',
'_DATA_TYPE_INVALID_' => 'Illegal data objects!',
'_OPERATION_WRONG_' => 'Operation error occurs',
'_NOT_LOAD_DB_' => 'Unable to load the database',
'_NO_DB_DRIVER_' => 'Unable to load database driver',
'_NOT_SUPPORT_DB_' => 'The system is temporarily not support database',
'_NO_DB_CONFIG_' => 'Not define the database configuration',
'_NOT_SUPPORT_' => 'The system does not support',
'_CACHE_TYPE_INVALID_' => 'Unable to load the cache type',
'_FILE_NOT_WRITABLE_' => 'Directory (file) is not writable',
'_METHOD_NOT_EXIST_' => 'The method you requested does not exist!',
'_CLASS_NOT_EXIST_' => 'Instantiating a class does not exist!',
'_CLASS_CONFLICT_' => 'Class name conflicts',
'_TEMPLATE_ERROR_' => 'Template Engine errors',
'_CACHE_WRITE_ERROR_' => 'Cache file write failed!',
'_TAGLIB_NOT_EXIST_' => 'Tag library is not defined',
'_OPERATION_FAIL_' => 'Operation failed!',
'_OPERATION_SUCCESS_' => 'Operation succeed!',
'_SELECT_NOT_EXIST_' => 'Record does not exist!',
'_EXPRESS_ERROR_' => 'Expression errors',
'_TOKEN_ERROR_' => "Form's token errors",
'_RECORD_HAS_UPDATE_' => 'Record has been updated',
'_NOT_ALLOW_PHP_' => 'PHP codes are not allowed in the template',
'_PARAM_ERROR_' => 'Parameter error or undefined',
'_ERROR_QUERY_EXPRESS_' => 'Query express error',
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Daiane Azevedo <daianeaze16@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP Portuguese language package
*/
return array(
/* core language package */
'_MODULE_NOT_EXIST_' => "Módulo não pode ser carregado",
'_CONTROLLER_NOT_EXIST_' => "Controller não pode ser carregado",
'_ERROR_ACTION_' => 'Ação ilegal',
'_LANGUAGE_NOT_LOAD_' => "Não é possível carregar pacote da linguagem",
'_TEMPLATE_NOT_EXIST_' => "Template não existe",
'_MODULE_' => 'Módulo',
'_ACTION_' => 'Ação',
'_MODEL_NOT_EXIST_' => "Modelo não pode ser carregado",
'_VALID_ACCESS_' => 'Sem acesso',
'_XML_TAG_ERROR_' => 'Erro de sintaxe - XML tag',
'_DATA_TYPE_INVALID_' => 'Tipos de dados ilegais!',
'_OPERATION_WRONG_' => 'Erro na operação',
'_NOT_LOAD_DB_' => 'Impossível carregar banco de dados',
'_NO_DB_DRIVER_' => 'Impossível carregar driver do bando de dados',
'_NOT_SUPPORT_DB_' => 'Temporariamente sem suporte ao banco',
'_NO_DB_CONFIG_' => 'Não define a configuração do banco',
'_NOT_SUPPORT_' => 'O sistema não suporta',
'_CACHE_TYPE_INVALID_' => 'Impossível carregar o tipo de cache',
'_FILE_NOT_WRITABLE_' => 'Diretório (arquivo) não pode ser escrito',
'_METHOD_NOT_EXIST_' => 'O método solicitado não existe!',
'_CLASS_NOT_EXIST_' => 'Não existe instância da classe',
'_CLASS_CONFLICT_' => 'Conflitos com nome da classe',
'_TEMPLATE_ERROR_' => 'Erros na contrução do template',
'_CACHE_WRITE_ERROR_' => 'Escrita do arquivo de cache falhou!',
'_TAGLIB_NOT_EXIST_' => 'Biblioteca da tag não foi definida',
'_OPERATION_FAIL_' => 'Operação falhou!',
'_OPERATION_SUCCESS_' => 'Operação bem sucessida!',
'_SELECT_NOT_EXIST_' => 'Gravação não existe!',
'_EXPRESS_ERROR_' => 'Erros de expressão',
'_TOKEN_ERROR_' => 'Erro no token do formulário',
'_RECORD_HAS_UPDATE_' => 'Gravação não foi atualizada',
'_NOT_ALLOW_PHP_' => 'Código PHP não é permitido no template',
'_PARAM_ERROR_' => 'Parâmetro errado ou indefinido',
'_ERROR_QUERY_EXPRESS_' => 'Erros na expressão da query',
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP 简体中文语言包
*/
return array(
/* 核心语言变量 */
'_MODULE_NOT_EXIST_' => '无法加载模块',
'_CONTROLLER_NOT_EXIST_' => '无法加载控制器',
'_ERROR_ACTION_' => '非法操作',
'_LANGUAGE_NOT_LOAD_' => '无法加载语言包',
'_TEMPLATE_NOT_EXIST_' => '模板不存在',
'_MODULE_' => '模块',
'_ACTION_' => '操作',
'_MODEL_NOT_EXIST_' => '模型不存在或者没有定义',
'_VALID_ACCESS_' => '没有权限',
'_XML_TAG_ERROR_' => 'XML标签语法错误',
'_DATA_TYPE_INVALID_' => '非法数据对象!',
'_OPERATION_WRONG_' => '操作出现错误',
'_NOT_LOAD_DB_' => '无法加载数据库',
'_NO_DB_DRIVER_' => '无法加载数据库驱动',
'_NOT_SUPPORT_DB_' => '系统暂时不支持数据库',
'_NO_DB_CONFIG_' => '没有定义数据库配置',
'_NOT_SUPPORT_' => '系统不支持',
'_CACHE_TYPE_INVALID_' => '无法加载缓存类型',
'_FILE_NOT_WRITABLE_' => '目录(文件)不可写',
'_METHOD_NOT_EXIST_' => '方法不存在!',
'_CLASS_NOT_EXIST_' => '实例化一个不存在的类!',
'_CLASS_CONFLICT_' => '类名冲突',
'_TEMPLATE_ERROR_' => '模板引擎错误',
'_CACHE_WRITE_ERROR_' => '缓存文件写入失败!',
'_TAGLIB_NOT_EXIST_' => '标签库未定义',
'_OPERATION_FAIL_' => '操作失败!',
'_OPERATION_SUCCESS_' => '操作成功!',
'_SELECT_NOT_EXIST_' => '记录不存在!',
'_EXPRESS_ERROR_' => '表达式错误',
'_TOKEN_ERROR_' => '表单令牌错误',
'_RECORD_HAS_UPDATE_' => '记录已经更新',
'_NOT_ALLOW_PHP_' => '模板禁用PHP代码',
'_PARAM_ERROR_' => '参数错误或者未定义',
'_ERROR_QUERY_EXPRESS_' => '错误的查询条件',
);
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* ThinkPHP 繁体中文語言包
*/
return array(
/* 核心語言變數 */
'_MODULE_NOT_EXIST_' => '無法載入模組',
'_CONTROLLER_NOT_EXIST_' => '無法載入控制器',
'_ERROR_ACTION_' => '非法操作',
'_LANGUAGE_NOT_LOAD_' => '無法載入語言包',
'_TEMPLATE_NOT_EXIST_' => '模板不存在',
'_MODULE_' => '模組',
'_ACTION_' => '操作',
'_MODEL_NOT_EXIST_' => '模型不存在或者沒有定義',
'_VALID_ACCESS_' => '沒有權限',
'_XML_TAG_ERROR_' => 'XML標籤語法錯誤',
'_DATA_TYPE_INVALID_' => '非法資料物件!',
'_OPERATION_WRONG_' => '操作出現錯誤',
'_NOT_LOAD_DB_' => '無法載入資料庫',
'_NO_DB_DRIVER_' => '無法載入資料庫驅動',
'_NOT_SUPPORT_DB_' => '系統暫時不支援資料庫',
'_NO_DB_CONFIG_' => '沒有定義資料庫設定',
'_NOT_SUPPORT_' => '系統不支援',
'_CACHE_TYPE_INVALID_' => '無法載入快取類型',
'_FILE_NOT_WRITABLE_' => '目錄(檔案)不可寫',
'_METHOD_NOT_EXIST_' => '方法不存在!',
'_CLASS_NOT_EXIST_' => '實例化一個不存在的類別!',
'_CLASS_CONFLICT_' => '類別名稱衝突',
'_TEMPLATE_ERROR_' => '模板引擎錯誤',
'_CACHE_WRITE_ERROR_' => '快取檔案寫入失敗!',
'_TAGLIB_NOT_EXIST_' => '標籤庫未定義',
'_OPERATION_FAIL_' => '操作失敗!',
'_OPERATION_SUCCESS_' => '操作成功!',
'_SELECT_NOT_EXIST_' => '記錄不存在!',
'_EXPRESS_ERROR_' => '運算式錯誤',
'_TOKEN_ERROR_' => '表單權限錯誤',
'_RECORD_HAS_UPDATE_' => '記錄已經更新',
'_NOT_ALLOW_PHP_' => '模板禁用PHP代碼',
'_PARAM_ERROR_' => '參數錯誤或者未定義',
'_ERROR_QUERY_EXPRESS_' => '錯誤的查詢條件',
);
<?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>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 行为扩展:代理检测
*/
class AgentCheckBehavior {
public function run(&$params) {
// 代理访问检测
$limitProxyVisit = C('LIMIT_PROXY_VISIT',null,true);
if($limitProxyVisit && ($_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>
// +----------------------------------------------------------------------
namespace Behavior;
use Think\Think;
/**
* Boris行为扩展
*/
class BorisBehavior {
public function run(&$params) {
if(IS_CLI){
if(!function_exists('pcntl_signal'))
E("pcntl_signal not working.\nRepl mode based on Linux OS or PHP for OS X(http://php-osx.liip.ch/)\n");
Think::addMap(array(
'Boris\Boris' => VENDOR_PATH . 'Boris/Boris.php',
'Boris\Config' => VENDOR_PATH . 'Boris/Config.php',
'Boris\CLIOptionsHandler' => VENDOR_PATH . 'Boris/CLIOptionsHandler.php',
'Boris\ColoredInspector' => VENDOR_PATH . 'Boris/ColoredInspector.php',
'Boris\DumpInspector' => VENDOR_PATH . 'Boris/DumpInspector.php',
'Boris\EvalWorker' => VENDOR_PATH . 'Boris/EvalWorker.php',
'Boris\ExportInspector' => VENDOR_PATH . 'Boris/ExportInspector.php',
'Boris\Inspector' => VENDOR_PATH . 'Boris/Inspector.php',
'Boris\ReadlineClient' => VENDOR_PATH . 'Boris/ReadlineClient.php',
'Boris\ShallowParser' => VENDOR_PATH . 'Boris/ShallowParser.php',
));
$boris = new \Boris\Boris(">>> ");
$config = new \Boris\Config();
$config->apply($boris, true);
$options = new \Boris\CLIOptionsHandler();
$options->handle($boris);
$boris->onStart(sprintf("echo 'REPL MODE FOR THINKPHP \nTHINKPHP_VERSION: %s, PHP_VERSION: %s, BORIS_VERSION: %s\n';", THINK_VERSION, PHP_VERSION, $boris::VERSION));
$boris->start();
}
}
}
<?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>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 浏览器防刷新检测
*/
class BrowserCheckBehavior {
public function run(&$params) {
if($_SERVER['REQUEST_METHOD'] == 'GET') {
// 启用页面防刷新机制
$guid = md5($_SERVER['PHP_SELF']);
// 浏览器防刷新的时间间隔(秒) 默认为10
$refleshTime = C('LIMIT_REFLESH_TIMES',null,10);
// 检查页面刷新间隔
if(cookie('_last_visit_time_'.$guid) && cookie('_last_visit_time_'.$guid)>time()-$refleshTime) {
// 页面刷新读取浏览器缓存
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');
}
}
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Behavior;
// 创建Lite运行文件
// 可以替换框架入口文件运行
// 建议绑定位置app_init
class BuildLiteBehavior {
public function run(&$params) {
if(!defined('BUILD_LITE_FILE')) return ;
$litefile = C('RUNTIME_LITE_FILE',null,RUNTIME_PATH.'lite.php');
if(is_file($litefile)) return;
$defs = get_defined_constants(TRUE);
$content = 'namespace {$GLOBALS[\'_beginTime\'] = microtime(TRUE);';
if(MEMORY_LIMIT_ON) {
$content .= '$GLOBALS[\'_startUseMems\'] = memory_get_usage();';
}
// 生成数组定义
unset($defs['user']['BUILD_LITE_FILE']);
$content .= $this->buildArrayDefine($defs['user']).'}';
// 读取编译列表文件
$filelist = is_file(CONF_PATH.'lite.php')?
include CONF_PATH.'lite.php':
array(
THINK_PATH.'Common/functions.php',
COMMON_PATH.'Common/function.php',
CORE_PATH . 'Think'.EXT,
CORE_PATH . 'Hook'.EXT,
CORE_PATH . 'App'.EXT,
CORE_PATH . 'Dispatcher'.EXT,
CORE_PATH . 'Log'.EXT,
CORE_PATH . 'Log/Driver/File'.EXT,
CORE_PATH . 'Route'.EXT,
CORE_PATH . 'Controller'.EXT,
CORE_PATH . 'View'.EXT,
CORE_PATH . 'Storage'.EXT,
CORE_PATH . 'Storage/Driver/File'.EXT,
CORE_PATH . 'Exception'.EXT,
BEHAVIOR_PATH . 'ParseTemplateBehavior'.EXT,
BEHAVIOR_PATH . 'ContentReplaceBehavior'.EXT,
);
// 编译文件
foreach ($filelist as $file){
if(is_file($file)) {
$content .= compile($file);
}
}
// 处理Think类的start方法
$content = preg_replace('/\$runtimefile = RUNTIME_PATH(.+?)(if\(APP_STATUS)/','\2',$content,1);
$content .= "\nnamespace { Think\Think::addMap(".var_export(\Think\Think::getMap(),true).");";
$content .= "\nL(".var_export(L(),true).");\nC(".var_export(C(),true).');Think\Hook::import('.var_export(\Think\Hook::get(),true).');Think\Think::start();}';
// 生成运行Lite文件
file_put_contents($litefile,strip_whitespace('<?php '.$content));
}
// 根据数组生成常量定义
private function buildArrayDefine($array) {
$content = "\n";
foreach ($array as $key => $val) {
$key = strtoupper($key);
$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;
}
}
\ No newline at end of file
<?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>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 系统行为扩展:操作路由检测
*/
class CheckActionRouteBehavior {
// 行为扩展的执行入口必须是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;
}
}
\ No newline at end of file
<?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>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 语言检测 并自动加载语言包
*/
class CheckLangBehavior {
// 行为扩展的执行入口必须是run
public function run(&$params){
// 检测语言
$this->checkLanguage();
}
/**
* 语言检查
* 检查浏览器支持语言,并自动加载语言包
* @access private
* @return void
*/
private function checkLanguage() {
// 不开启语言包功能,仅仅加载框架语言文件直接返回
if (!C('LANG_SWITCH_ON',null,false)){
return;
}
$langSet = C('DEFAULT_LANG');
$varLang = C('VAR_LANGUAGE',null,'l');
$langList = C('LANG_LIST',null,'zh-cn');
// 启用了语言包功能
// 根据是否启用自动侦测设置获取语言选择
if (C('LANG_AUTO_DETECT',null,true)){
if(isset($_GET[$varLang])){
$langSet = $_GET[$varLang];// 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($langList,$langSet)) { // 非法语言参数
$langSet = C('DEFAULT_LANG');
}
}
// 定义当前语言
define('LANG_SET',strtolower($langSet));
// 读取框架语言包
$file = THINK_PATH.'Lang/'.LANG_SET.'.php';
if(LANG_SET != C('DEFAULT_LANG') && is_file($file))
L(include $file);
// 读取应用公共语言包
$file = LANG_PATH.LANG_SET.'.php';
if(is_file($file))
L(include $file);
// 读取模块语言包
$file = MODULE_PATH.'Lang/'.LANG_SET.'.php';
if(is_file($file))
L(include $file);
// 读取当前控制器语言包
$file = MODULE_PATH.'Lang/'.LANG_SET.'/'.strtolower(CONTROLLER_NAME).'.php';
if (is_file($file))
L(include $file);
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 系统行为扩展:模板内容输出替换
*/
class ContentReplaceBehavior {
// 行为扩展的执行入口必须是run
public function run(&$content){
$content = $this->templateContentReplace($content);
}
/**
* 模板内容替换
* @access protected
* @param string $content 模板内容
* @return string
*/
protected function templateContentReplace($content) {
// 系统默认的特殊变量替换
$replace = array(
'__ROOT__' => __ROOT__, // 当前网站地址
'__APP__' => __APP__, // 当前应用地址
'__MODULE__' => __MODULE__,
'__ACTION__' => __ACTION__, // 当前操作地址
'__SELF__' => htmlentities(__SELF__), // 当前页面地址
'__CONTROLLER__'=> __CONTROLLER__,
'__URL__' => __CONTROLLER__,
'__PUBLIC__' => __ROOT__.'/Public',// 站点公共目录
);
// 允许用户自定义模板的字符串替换
if(is_array(C('TMPL_PARSE_STRING')) )
$replace = array_merge($replace,C('TMPL_PARSE_STRING'));
$content = str_replace(array_keys($replace),array_values($replace),$content);
return $content;
}
}
\ No newline at end of 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>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 自动执行任务
*/
class CronRunBehavior {
public function run(&$params) {
// 锁定自动执行
$lockfile = RUNTIME_PATH.'cron.lock';
if(is_writable($lockfile) && filemtime($lockfile) > $_SERVER['REQUEST_TIME'] - C('CRON_MAX_TIME',null,60)) {
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(COMMON_PATH.'Conf/crons.php')){
$crons = include COMMON_PATH.'Conf/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 COMMON_PATH.'Cron/'.$cron[0].'.php';
G('cronEnd');
$_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执行日志
\Think\Log::write(implode('',$log));
// 更新cron文件
$content = "<?php\nreturn ".var_export($crons,true).";\n?>";
file_put_contents(RUNTIME_PATH.'~crons.php',$content);
}
}
// 解除锁定
unlink($lockfile);
return ;
}
}
\ No newline at end of file
This diff is collapsed.
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Behavior;
use Think\Storage;
use Think\Think;
/**
* 系统行为扩展:模板解析
*/
class ParseTemplateBehavior {
// 行为扩展的执行入口必须是run
public function run(&$_data){
$engine = strtolower(C('TMPL_ENGINE_TYPE'));
$_content = empty($_data['content'])?$_data['file']:$_data['content'];
$_data['prefix'] = !empty($_data['prefix'])?$_data['prefix']:C('TMPL_CACHE_PREFIX');
if('think'==$engine){ // 采用Think模板引擎
if((!empty($_data['content']) && $this->checkContentCache($_data['content'],$_data['prefix']))
|| $this->checkCache($_data['file'],$_data['prefix'])) { // 缓存有效
//载入模版缓存文件
Storage::load(C('CACHE_PATH').$_data['prefix'].md5($_content).C('TMPL_CACHFILE_SUFFIX'),$_data['var']);
}else{
$tpl = Think::instance('Think\\Template');
// 编译并加载模板文件
$tpl->fetch($_content,$_data['var'],$_data['prefix']);
}
}else{
// 调用第三方模板引擎解析和输出
if(strpos($engine,'\\')){
$class = $engine;
}else{
$class = 'Think\\Template\\Driver\\'.ucwords($engine);
}
if(class_exists($class)) {
$tpl = new $class;
$tpl->fetch($_content,$_data['var']);
}else { // 类没有定义
E(L('_NOT_SUPPORT_').': ' . $class);
}
}
}
/**
* 检查缓存文件是否有效
* 如果无效则需要重新编译
* @access public
* @param string $tmplTemplateFile 模板文件名
* @return boolean
*/
protected function checkCache($tmplTemplateFile,$prefix='') {
if (!C('TMPL_CACHE_ON')) // 优先对配置设定检测
return false;
$tmplCacheFile = C('CACHE_PATH').$prefix.md5($tmplTemplateFile).C('TMPL_CACHFILE_SUFFIX');
if(!Storage::has($tmplCacheFile)){
return false;
}elseif (filemtime($tmplTemplateFile) > Storage::get($tmplCacheFile,'mtime')) {
// 模板文件如果有更新则缓存需要更新
return false;
}elseif (C('TMPL_CACHE_TIME') != 0 && time() > Storage::get($tmplCacheFile,'mtime')+C('TMPL_CACHE_TIME')) {
// 缓存是否在有效期
return false;
}
// 开启布局模板
if(C('LAYOUT_ON')) {
$layoutFile = THEME_PATH.C('LAYOUT_NAME').C('TMPL_TEMPLATE_SUFFIX');
if(filemtime($layoutFile) > Storage::get($tmplCacheFile,'mtime')) {
return false;
}
}
// 缓存有效
return true;
}
/**
* 检查缓存内容是否有效
* 如果无效则需要重新编译
* @access public
* @param string $tmplContent 模板内容
* @return boolean
*/
protected function checkContentCache($tmplContent,$prefix='') {
if(Storage::has(C('CACHE_PATH').$prefix.md5($tmplContent).C('TMPL_CACHFILE_SUFFIX'))){
return true;
}else{
return false;
}
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Behavior;
use Think\Storage;
/**
* 系统行为扩展:静态缓存读取
*/
class ReadHtmlCacheBehavior {
// 行为扩展的执行入口必须是run
public function run(&$params){
// 开启静态缓存
if(IS_GET && C('HTML_CACHE_ON')) {
$cacheTime = $this->requireHtmlCache();
if( false !== $cacheTime && $this->checkHTMLCache(HTML_FILE_NAME,$cacheTime)) { //静态页面有效
// 读取静态页面输出
echo Storage::read(HTML_FILE_NAME,'html');
exit();
}
}
}
// 判断是否需要静态缓存
static private function requireHtmlCache() {
// 分析当前的静态规则
$htmls = C('HTML_CACHE_RULES'); // 读取静态规则
if(!empty($htmls)) {
$htmls = array_change_key_case($htmls);
// 静态规则文件定义格式 actionName=>array('静态规则','缓存时间','附加规则')
// 'read'=>array('{id},{name}',60,'md5') 必须保证静态规则的唯一性 和 可判断性
// 检测静态规则
$controllerName = strtolower(CONTROLLER_NAME);
$actionName = strtolower(ACTION_NAME);
if(isset($htmls[$controllerName.':'.$actionName])) {
$html = $htmls[$controllerName.':'.$actionName]; // 某个控制器的操作的静态规则
}elseif(isset($htmls[$controllerName.':'])){// 某个控制器的静态规则
$html = $htmls[$controllerName.':'];
}elseif(isset($htmls[$actionName])){
$html = $htmls[$actionName]; // 所有操作的静态规则
}elseif(isset($htmls['*'])){
$html = $htmls['*']; // 全局静态规则
}
if(!empty($html)) {
// 解读静态规则
$rule = is_array($html)?$html[0]:$html;
// 以$_开头的系统变量
$callback = function($match){
switch($match[1]){
case '_GET': $var = $_GET[$match[2]]; break;
case '_POST': $var = $_POST[$match[2]]; break;
case '_REQUEST': $var = $_REQUEST[$match[2]]; break;
case '_SERVER': $var = $_SERVER[$match[2]]; break;
case '_SESSION': $var = $_SESSION[$match[2]]; break;
case '_COOKIE': $var = $_COOKIE[$match[2]]; break;
}
return (count($match) == 4) ? $match[3]($var) : $var;
};
$rule = preg_replace_callback('/{\$(_\w+)\.(\w+)(?:\|(\w+))?}/', $callback, $rule);
// {ID|FUN} GET变量的简写
$rule = preg_replace_callback('/{(\w+)\|(\w+)}/', function($match){return $match[2]($_GET[$match[1]]);}, $rule);
$rule = preg_replace_callback('/{(\w+)}/', function($match){return $_GET[$match[1]];}, $rule);
// 特殊系统变量
$rule = str_ireplace(
array('{:controller}','{:action}','{:module}'),
array(CONTROLLER_NAME,ACTION_NAME,MODULE_NAME),
$rule);
// {|FUN} 单独使用函数
$rule = preg_replace_callback('/{|(\w+)}/', function($match){return $match[1]();},$rule);
$cacheTime = C('HTML_CACHE_TIME',null,60);
if(is_array($html)){
if(!empty($html[2])) $rule = $html[2]($rule); // 应用附加函数
$cacheTime = isset($html[1])?$html[1]:$cacheTime; // 缓存有效期
}else{
$cacheTime = $cacheTime;
}
// 当前缓存文件
define('HTML_FILE_NAME',HTML_PATH . $rule.C('HTML_FILE_SUFFIX',null,'.html'));
return $cacheTime;
}
}
// 无需缓存
return false;
}
/**
* 检查静态HTML文件是否有效
* 如果无效需要重新更新
* @access public
* @param string $cacheFile 静态文件名
* @param integer $cacheTime 缓存有效期
* @return boolean
*/
static public function checkHTMLCache($cacheFile='',$cacheTime='') {
if(!is_file($cacheFile) && 'sae' != APP_MODE ){
return false;
}elseif (filemtime(\Think\Think::instance('Think\View')->parseTemplate()) > Storage::get($cacheFile,'mtime','html')) {
// 模板文件如果更新静态文件需要更新
return false;
}elseif(!is_numeric($cacheTime) && function_exists($cacheTime)){
return $cacheTime($cacheFile);
}elseif ($cacheTime != 0 && NOW_TIME > Storage::get($cacheFile,'mtime','html')+$cacheTime) {
// 文件是否在有效期
return false;
}
//静态文件有效
return true;
}
}
\ No newline at end of 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>
// +----------------------------------------------------------------------
namespace Behavior;
/**
* 机器人检测
* @author liu21st <liu21st@gmail.com>
*/
class RobotCheckBehavior {
public function run(&$params) {
// 机器人访问检测
if(C('LIMIT_ROBOT_VISIT',null,true) && 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;
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Behavior;
use Think\Log;
/**
* 系统行为扩展:页面Trace显示输出
*/
class ShowPageTraceBehavior {
protected $tracePageTabs = array('BASE'=>'基本','FILE'=>'文件','INFO'=>'流程','ERR|NOTIC'=>'错误','SQL'=>'SQL','DEBUG'=>'调试');
// 行为扩展的执行入口必须是run
public function run(&$params){
if(!IS_AJAX && !IS_CLI && C('SHOW_PAGE_TRACE')) {
echo $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(),
'吞吐率' => number_format(1/G('beginTime','viewEndTime'),2).'req/s',
'内存开销' => 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 = COMMON_PATH.'Conf/trace.php';
if(is_file($traceFile)) {
$base = array_merge($base,include $traceFile);
}
$debug = trace();
$tabs = C('TRACE_PAGE_TABS',null,$this->tracePageTabs);
foreach ($tabs as $name=>$title){
switch(strtoupper($name)) {
case 'BASE':// 基本信息
$trace[$title] = $base;
break;
case 'FILE': // 文件信息
$trace[$title] = $info;
break;
default:// 调试信息
$name = strtoupper($name);
if(strpos($name,'|')) {// 多组信息
$names = explode('|',$name);
$result = array();
foreach($names as $name){
$result += isset($debug[$name])?$debug[$name]:array();
}
$trace[$title] = $result;
}else{
$trace[$title] = isset($debug[$name])?$debug[$name]:'';
}
}
}
if($save = C('PAGE_TRACE_SAVE')) { // 保存页面Trace日志
if(is_array($save)) {// 选择选项卡保存
$tabs = C('TRACE_PAGE_TABS',null,$this->tracePageTabs);
$array = array();
foreach ($save as $tab){
$array[] = $tabs[$tab];
}
}
$content = date('[ c ]').' '.get_client_ip().' '.$_SERVER['REQUEST_URI']."\r\n";
foreach ($trace as $key=>$val){
if(!isset($array) || in_array_case($key,$array)) {
$content .= '[ '.$key." ]\r\n";
if(is_array($val)) {
foreach ($val as $k=>$v){
$content .= (!is_numeric($k)?$k.':':'').print_r($v,true)."\r\n";
}
}else{
$content .= print_r($val,true)."\r\n";
}
$content .= "\r\n";
}
}
error_log(str_replace('<br/>',"\r\n",$content), 3,C('LOG_PATH').date('y_m_d').'_trace.log');
}
unset($files,$info,$base);
// 调用Trace页面模板
ob_start();
include C('TMPL_TRACE_FILE')?C('TMPL_TRACE_FILE'):THINK_PATH.'Tpl/page_trace.tpl';
return ob_get_clean();
}
/**
* 获取运行时间
*/
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 )';
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Behavior;
use Think\Storage;
/**
* 系统行为扩展:静态缓存写入
*/
class WriteHtmlCacheBehavior {
// 行为扩展的执行入口必须是run
public function run(&$content) {
//2014-11-28 修改 如果有HTTP 4xx 3xx 5xx 头部,禁止存储
//2014-12-1 修改 对注入的网址 防止生成,例如 /game/lst/SortType/hot/-e8-90-8c-e5-85-94-e7-88-b1-e6-b6-88-e9-99-a4/-e8-bf-9b-e5-87-bb-e7-9a-84-e9-83-a8-e8-90-bd/-e9-a3-8e-e4-ba-91-e5-a4-a9-e4-b8-8b/index.shtml
if (C('HTML_CACHE_ON') && defined('HTML_FILE_NAME')
&& !preg_match('/Status.*[345]{1}\d{2}/i', implode(' ', headers_list()))
&& !preg_match('/(-[a-z0-9]{2}){3,}/i',HTML_FILE_NAME)) {
//静态文件写入
Storage::put(HTML_FILE_NAME, $content, 'html');
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
1.1.4
2010100721
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment