PHP开源系统学习之fluxbb_2
谴责下某位同学,转载了我的上一篇文章,也不给个原文地址,希望这次再来转时能加上。
//检查登录,在common.php判断
//cookie串: 2|dc4fab5bb354be5104bae0affe2c1b615c565cf5|1384165106|eb084e693bb241a29e9986b62e69cf5f465f354d
//cookie有效期大于当前时间=》继续判断:用户cookie中保存的用户ID、生存周期、及预设置的cookie密钥,经过特殊处理后与$cookie['cookie_hash']比较
function check_cookie(&$pun_user)
{
global $db, $db_type, $pun_config, $cookie_name, $cookie_seed; $now = time(); // If the cookie is set and it matches the correct pattern, then read the values from it
if (isset($_COOKIE[$cookie_name]) && preg_match('%^(\d+)\|([0-9a-fA-F]+)\|(\d+)\|([0-9a-fA-F]+)$%', $_COOKIE[$cookie_name], $matches))
{
$cookie = array(
'user_id' => intval($matches[1]),
'password_hash' => $matches[2],
'expiration_time' => intval($matches[3]),
'cookie_hash' => $matches[4],
);
} // If it has a non-guest user, and hasn't expired
if (isset($cookie) && $cookie['user_id'] > 1 && $cookie['expiration_time'] > $now)
{
// If the cookie has been tampered with
if (forum_hmac($cookie['user_id'].'|'.$cookie['expiration_time'], $cookie_seed.'_cookie_hash') != $cookie['cookie_hash'])
{
$expire = $now + 31536000; // The cookie expires after a year
pun_setcookie(1, pun_hash(uniqid(rand(), true)), $expire);
set_default_user(); return;
}
...............
//从上面得到的$cookie变量中的user_id,去数据库查询取到密码,特殊处理后与$cookie中的password_hash比较
// Check if there's a user with the user ID and password hash from the cookie
$result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE u.id='.intval($cookie['user_id'])) or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
$pun_user = $db->fetch_assoc($result); // If user authorisation failed
if (!isset($pun_user['id']) || forum_hmac($pun_user['password'], $cookie_seed.'_password_hash') !== $cookie['password_hash'])
{
$expire = $now + 31536000; // The cookie expires after a year
pun_setcookie(1, pun_hash(uniqid(rand(), true)), $expire);
set_default_user(); return;
}
//退出 "login.php?action=out&id=2&csrf_token=40ce5abbaf76ba6fe66bb8a833eb9e8d4da5c273" ,此处没有直接删除cookie
//先判断用户是否已登录,链接是否有相应的标识
if ($action == 'out')
{
if ($pun_user['is_guest'] || !isset($_GET['id']) || $_GET['id'] != $pun_user['id'] || !isset($_GET['csrf_token']) || $_GET['csrf_token'] != pun_hash($pun_user['id'].pun_hash(get_remote_address())))
{
header('Location: index.php');
exit;
} // Remove user from "users online" list
$db->query('DELETE FROM '.$db->prefix.'online WHERE user_id='.$pun_user['id']) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error()); // Update last_visit (make sure there's something to update it with)
if (isset($pun_user['logged']))
$db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error()); pun_setcookie(1, pun_hash(uniqid(rand(), true)), time() + 31536000); redirect('index.php', $lang_login['Logout redirect']);
}
//get_remote_address()取远程IP,区分了是否用了代理
function get_remote_address()
{
$remote_addr = $_SERVER['REMOTE_ADDR']; // If we are behind a reverse proxy try to find the real users IP
if (defined('FORUM_BEHIND_REVERSE_PROXY'))
{
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
{
// The general format of the field is:
// X-Forwarded-For: client1, proxy1, proxy2
// where the value is a comma+space separated list of IP addresses, the left-most being the farthest downstream client,
// and each successive proxy that passed the request adding the IP address where it received the request from.
$forwarded_for = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$forwarded_for = trim($forwarded_for[0]); if (@preg_match('%^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$%', $forwarded_for) || @preg_match('%^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$%', $forwarded_for))
$remote_addr = $forwarded_for;
}
} return $remote_addr;
}
//退出时cookie处理
pun_setcookie(1, pun_hash(uniqid(rand(), true)), time() + 31536000);
// Set a cookie, FluxBB style!
// Wrapper for forum_setcookie
//
function pun_setcookie($user_id, $password_hash, $expire)
{
global $cookie_name, $cookie_seed; forum_setcookie($cookie_name, $user_id.'|'.forum_hmac($password_hash, $cookie_seed.'_password_hash').'|'.$expire.'|'.forum_hmac($user_id.'|'.$expire, $cookie_seed.'_cookie_hash'), $expire);
} //
// Set a cookie, FluxBB style!
//
function forum_setcookie($name, $value, $expire)
{
global $cookie_path, $cookie_domain, $cookie_secure, $pun_config; if ($expire - time() - $pun_config['o_timeout_visit'] < 1)
$expire = 0; // Enable sending of a P3P header
header('P3P: CP="CUR ADM"'); if (version_compare(PHP_VERSION, '5.2.0', '>='))
setcookie($name, $value, $expire, $cookie_path, $cookie_domain, $cookie_secure, true);
else
setcookie($name, $value, $expire, $cookie_path.'; HttpOnly', $cookie_domain, $cookie_secure);
}
//定义一些通用函数,
如:error():
error('Unable to fetch user info', __FILE__, __LINE__, $db->error())
message($message, $no_back_link = false, $http_status = null)
utf8_trim( $str, $charlist=false); //去空格
redirect($destination_url, $message); //重定向
fluxbb多数页面都写在一个文件中,如login.php包括登录、退出、忘记密码等操作,通过不同的action区分。
引入公用header.php、不同页面分别替换相应的内容($pun_user变量),如title、要加载的css等。
$pun_user变量前面提到的check_cookie()函数中设置的值。
$pun_user = array();
check_cookie($pun_user);
function check_cookie(&$pun_user){} //注意后面的&地址符
check_cookie(函数中,通过cookie值来判断用户信息,如是合法的已登录用户,直接将一些值保存到$pun_user,否则设置一些默认值。通过set_default_user()函数,并记录在线用户。
//
// Fill $pun_user with default values (for guests)
//
function set_default_user()
{
global $db, $db_type, $pun_user, $pun_config; $remote_addr = get_remote_address(); // Fetch guest user
$result = $db->query('SELECT u.*, g.*, o.logged, o.last_post, o.last_search FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.ident=\''.$db->escape($remote_addr).'\' WHERE u.id=1') or error('Unable to fetch guest information', __FILE__, __LINE__, $db->error());
if (!$db->num_rows($result))
exit('Unable to fetch guest information. Your database must contain both a guest user and a guest user group.'); $pun_user = $db->fetch_assoc($result); // Update online list
if (!$pun_user['logged'])
{
$pun_user['logged'] = time(); // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table
switch ($db_type)
{
case 'mysql':
case 'mysqli':
case 'mysql_innodb':
case 'mysqli_innodb':
case 'sqlite':
$db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
break; default:
$db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) SELECT 1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].' WHERE NOT EXISTS (SELECT 1 FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($remote_addr).'\')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
break;
}
}
else
$db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Unable to update online list', __FILE__, __LINE__, $db->error()); $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
$pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
$pun_user['timezone'] = $pun_config['o_default_timezone'];
$pun_user['dst'] = $pun_config['o_default_dst'];
$pun_user['language'] = $pun_config['o_default_lang'];
$pun_user['style'] = $pun_config['o_default_style'];
$pun_user['is_guest'] = true;
$pun_user['is_admmod'] = false;
}
//footer.php
页面header和footer内容通过$tpl_main变量保存,footer.php最后,exit($tpl_main);直接输出并终止运行。主要用到了输出缓冲的一些函数。
在整个fluxbb系统中,只看到了两个js文件,分别是common.js和minmax.js,而且两个文件都没超过3kb,其中minmax.js是在header.php引入了。想想自己,没有jquery就有点寸步难行了。
原文作者:lltong,博客园地址:http://www.cnblogs.com/lltong/
PHP开源系统学习之fluxbb_2的更多相关文章
- PHP开源系统学习之fluxbb_1
		
最近一直忙于做项目,虽说做了点新东西.感觉自己进步不是很大,总体水平还是跟半年前差不多,想到的东西跟以前差不多,写出来的东西也跟以前差不多.只是现在做的东西多些,比以前敢做了. 近期准备利用点时间,读 ...
 - GitHub 上 57 款最流行的开源深度学习项目
		
转载:https://www.oschina.net/news/79500/57-most-popular-deep-learning-project-at-github GitHub 上 57 款最 ...
 - Computational Network Toolkit (CNTK) 是微软出品的开源深度学习工具包
		
Computational Network Toolkit (CNTK) 是微软出品的开源深度学习工具包 用 CNTK 搞深度学习 (一) 入门 Computational Network Toolk ...
 - Hibernate的系统 学习
		
Hibernate的系统 学习 一.Hibernate的介绍 1.什么是Hibernate? 首先,hibernate是数据持久层的一个轻量级框架.数据持久层的框架有很多比如:iBATIS,myBat ...
 - Ubuntu LTS 系统学习使用体会和实用工具软件汇总 6.04 8.04 10.04 12.04 14.04 16.04
		
Ubuntu LTS 系统学习体会和工具软件汇总 6.04 8.04 10.04 12.04 14.04 16.04 ubuntu入门必备pdf:http://download.csdn.net/de ...
 - MySQL如何系统学习
		
MySQL是当下互联网最流行的开源数据库.不管你使用或者学习何种编程语言,都将会使用到数据库,而MySQL则是应用最为广泛的数据库,没有之一! 之前在我的博客上也发布过一些MySQL优化配置项,都收到 ...
 - 开源深度学习架构Caffe
		
Caffe 全称为 Convolutional Architecture for Fast Feature Embedding,是一个被广泛使用的开源深度学习框架(在 TensorFlow 出现之前一 ...
 - 一种基于python的人脸识别开源系统
		
今天在搜索人脸识别的文章时,无意中搜到一个比较开源代码,介绍说是这个系统人脸的识别率 是比较高的,可以达到:99.38%.这么高的识别率,着实把我吓了一跳.抱着实事求是的态度.个人 就做了一些验证和研 ...
 - GitHub 上 57 款最流行的开源深度学习项目【转】
		
GitHub 上 57 款最流行的开源深度学习项目[转] 2017-02-19 20:09 334人阅读 评论(0) 收藏 举报 分类: deeplearning(28) from: https:// ...
 
随机推荐
- maven pom filter 导致的问题记录
			
Maven提供了一个很不错的功能 Resource Filter, 可以将按不同环境的进行变量赋值, 比如数据库链接, redis, 日志输出位置等等.. 具体的filter如何使用我这里不做介绍, ...
 - django1.8.2 建站实现分页显示功能
			
个人经验: django先写view,在再写url,最后写html文件. 要实现某个功能,先google查找相关文章,在到文档中寻找相关章节,最后本地实现功能. 1.django1.8.2 实现分页功 ...
 - C++(七)— 进程、线程及区别
			
1.进程(process) 狭义定义:进程就是一段程序的执行过程. 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,在传统的操作系统中,进程既 ...
 - PHP基础陷阱题(变量赋值)
			
PHP基础陷阱题代码,需要的朋友可以参考下 复制代码 代码如下: <?php $a=3; $b=6; if($a=5||$b=7){ $a++; $b++; } var_dump($a, $ ...
 - $.ajax()方法详解(转)
			
以下内容转自:http://www.cnblogs.com/tylerdonet/p/3520862.html 尊重原创,请访问原创文章 jquery中的ajax方法参数总是记不住,这里记录一下. ...
 - Selenium-几种元素定位方式
			
#识别元素并操作#一般有如下几种方法,其中id最为常用.这里需要注意识别元素一定要用唯一id 1.find_element_by_id("value") #! /usr/bin/e ...
 - QListWidget列表控件:当鼠标选中某行时,系统会自动设置选中的行的行号,用currentRow()返回回来,没有setCheck或setSelect类似函数
			
列表控件的设计思路: 只有QListWidgetItem自己能改变自己的状态(如checked,selected,颜色等)状态,QListWidget是无法改变其项的状态的. 列表控件是被动接受子项的 ...
 - 3_observer
			
#Observer 成就系统 achievements system 玩家完成某种成就后,通知监督者,监督者做出相应出来 ``` //简单来说就是事件触发的时候, 通知监督者 class Observ ...
 - codeforces 631A A. Interview
			
A. Interview time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
 - C++11特性  gcc源码包
			
1.下载gcc最新的源码包 2.解压缩 tar -xf gcc-4.9.1.tar.gz 3. cd gcc-4.9.1 4.运行download_prerequisites脚本, ./contri ...