#4 - ajout système de connexion (login poche mot de passe poche pour l'instant)

This commit is contained in:
nicosomb 2013-04-18 15:39:34 +02:00
parent b693a19e1c
commit e4d2565e05
15 changed files with 544 additions and 118 deletions

View file

@ -5,6 +5,7 @@ poche is based on :
* logo by Brightmix http://www.iconfinder.com/icondetails/43256/128/jeans_monotone_pocket_icon * logo by Brightmix http://www.iconfinder.com/icondetails/43256/128/jeans_monotone_pocket_icon
* icons http://icomoon.io * icons http://icomoon.io
* PHP Simple HTML DOM Parser (for Pocket import) http://simplehtmldom.sourceforge.net/ * PHP Simple HTML DOM Parser (for Pocket import) http://simplehtmldom.sourceforge.net/
* Session https://github.com/tontof/kriss_feed/blob/master/src/class/Session.php
poche is developed by Nicolas Lœuillet under the Do What the Fuck You Want to Public License poche is developed by Nicolas Lœuillet under the Do What the Fuck You Want to Public License

View file

@ -62,16 +62,15 @@ header {
color: #F1F1F1; color: #F1F1F1;
} }
/*#content {
width: 800px;
margin: 0 auto;
}*/
footer { footer {
text-align: right; text-align: right;
} }
/*** ***/
/*** LOGIN FORM ***/
ul#login li {
list-style-type: none;
}
/*** ***/ /*** ***/
/*** LINKS DISPLAY ***/ /*** LINKS DISPLAY ***/

View file

@ -30,7 +30,7 @@ else {
$url = $a[0]->href; $url = $a[0]->href;
action_to_do('add', $url, $token); action_to_do('add', $url);
if ($read == '1') { if ($read == '1') {
$last_id = $db->getHandle()->lastInsertId(); $last_id = $db->getHandle()->lastInsertId();
$sql_update = "UPDATE entries SET is_read=~is_read WHERE id=?"; $sql_update = "UPDATE entries SET is_read=~is_read WHERE id=?";

256
inc/MyTool.class.php Normal file
View file

@ -0,0 +1,256 @@
<?php
class MyTool
{
public static function initPhp()
{
define('START_TIME', microtime(true));
if (phpversion() < 5) {
die("Argh you don't have PHP 5 !");
}
error_reporting(E_ALL);
function stripslashesDeep($value) {
return is_array($value)
? array_map('stripslashesDeep', $value)
: stripslashes($value);
}
if (get_magic_quotes_gpc()) {
$_POST = array_map('stripslashesDeep', $_POST);
$_GET = array_map('stripslashesDeep', $_GET);
$_COOKIE = array_map('stripslashesDeep', $_COOKIE);
}
ob_start();
register_shutdown_function('ob_end_flush');
}
public static function isUrl($url)
{
// http://neo22s.com/check-if-url-exists-and-is-online-php/
$pattern='|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i';
return preg_match($pattern, $url);
}
public static function isEmail($email)
{
$pattern = "/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2, 4}$/i";
return (preg_match($pattern, $email));
}
public static function formatBBCode($text)
{
$replace = array(
'/\[m\](.+?)\[\/m\]/is'
=> '/* moderate */',
'/\[b\](.+?)\[\/b\]/is'
=> '<strong>$1</strong>',
'/\[i\](.+?)\[\/i\]/is'
=> '<em>$1</em>',
'/\[s\](.+?)\[\/s\]/is'
=> '<del>$1</del>',
'/\[u\](.+?)\[\/u\]/is'
=> '<span style="text-decoration: underline;">$1</span>',
'/\[url\](.+?)\[\/url]/is'
=> '<a href="$1">$1</a>',
'/\[url=(\w+:\/\/[^\]]+)\](.+?)\[\/url]/is'
=> '<a href="$1">$2</a>',
'/\[quote\](.+?)\[\/quote\]/is'
=> '<blockquote>$1</blockquote>',
'/\[code\](.+?)\[\/code\]/is'
=> '<code>$1</code>',
'/\[([^[]+)\|([^[]+)\]/is'
=> '<a href="$2">$1</a>'
);
$text = preg_replace(
array_keys($replace),
array_values($replace),
$text
);
return $text;
}
public static function formatText($text)
{
$text = preg_replace_callback(
'/<code_html>(.*?)<\/code_html>/is',
create_function(
'$matches',
'return htmlspecialchars($matches[1]);'
),
$text
);
$text = preg_replace_callback(
'/<code_php>(.*?)<\/code_php>/is',
create_function(
'$matches',
'return highlight_string("<?php $matches[1] ?>", true);'
),
$text
);
$text = preg_replace('/<br \/>/is', '', $text);
$text = preg_replace(
'#(^|\s)([a-z]+://([^\s\w/]?[\w/])*)(\s|$)#im',
'\\1<a href="\\2">\\2</a>\\4',
$text
);
$text = preg_replace(
'#(^|\s)wp:?([a-z]{2}|):([\w]+)#im',
'\\1<a href="http://\\2.wikipedia.org/wiki/\\3">\\3</a>',
$text
);
$text = str_replace(
'http://.wikipedia.org/wiki/',
'http://www.wikipedia.org/wiki/',
$text
);
$text = str_replace('\wp:', 'wp:', $text);
$text = str_replace('\http:', 'http:', $text);
$text = MyTool::formatBBCode($text);
$text = nl2br($text);
return $text;
}
public static function getUrl()
{
$https = (!empty($_SERVER['HTTPS'])
&& (strtolower($_SERVER['HTTPS']) == 'on'))
|| (isset($_SERVER["SERVER_PORT"])
&& $_SERVER["SERVER_PORT"] == '443'); // HTTPS detection.
$serverport = (!isset($_SERVER["SERVER_PORT"])
|| $_SERVER["SERVER_PORT"] == '80'
|| ($https && $_SERVER["SERVER_PORT"] == '443')
? ''
: ':' . $_SERVER["SERVER_PORT"]);
$scriptname = str_replace('/index.php', '/', $_SERVER["SCRIPT_NAME"]);
if (!isset($_SERVER["SERVER_NAME"])) {
return $scriptname;
}
return 'http' . ($https ? 's' : '') . '://'
. $_SERVER["SERVER_NAME"] . $serverport . $scriptname;
}
public static function rrmdir($dir)
{
if (is_dir($dir) && ($d = @opendir($dir))) {
while (($file = @readdir($d)) !== false) {
if ( $file == '.' || $file == '..' ) {
continue;
} else {
unlink($dir . '/' . $file);
}
}
}
}
public static function humanBytes($bytes)
{
$siPrefix = array( 'bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB' );
$base = 1024;
$class = min((int) log($bytes, $base), count($siPrefix) - 1);
$val = sprintf('%1.2f', $bytes / pow($base, $class));
return $val . ' ' . $siPrefix[$class];
}
public static function returnBytes($val)
{
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last)
{
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
public static function getMaxFileSize()
{
$sizePostMax = MyTool::returnBytes(ini_get('post_max_size'));
$sizeUploadMax = MyTool::returnBytes(ini_get('upload_max_filesize'));
// Return the smaller of two:
return min($sizePostMax, $sizeUploadMax);
}
public static function smallHash($text)
{
$t = rtrim(base64_encode(hash('crc32', $text, true)), '=');
// Get rid of characters which need encoding in URLs.
$t = str_replace('+', '-', $t);
$t = str_replace('/', '_', $t);
$t = str_replace('=', '@', $t);
return $t;
}
public static function renderJson($data)
{
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Content-type: application/json; charset=UTF-8');
echo json_encode($data);
exit();
}
public static function grabToLocal($url, $file, $force = false)
{
if ((!file_exists($file) || $force) && in_array('curl', get_loaded_extensions())){
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
$raw = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) {
$fp = fopen($file, 'x');
fwrite($fp, $raw);
fclose($fp);
}
curl_close ($ch);
}
}
public static function redirect($rurl = '')
{
if ($rurl === '') {
// if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['SERVER_NAME'])==0)
$rurl = (empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']);
if (isset($_POST['returnurl'])) {
$rurl = $_POST['returnurl'];
}
}
// prevent loop
if (empty($rurl) || parse_url($rurl, PHP_URL_QUERY) === $_SERVER['QUERY_STRING']) {
$rurl = MyTool::getUrl();
}
if (substr($rurl, 0, 1) !== '?') {
$ref = MyTool::getUrl();
if (substr($rurl, 0, strlen($ref)) !== $ref) {
$rurl = $ref;
}
}
header('Location: '.$rurl);
exit();
}
public static function silence_errors($num, $str)
{
// No-op
}
}

136
inc/Session.class.php Normal file
View file

@ -0,0 +1,136 @@
<?php
/**
* Session management class
* http://www.developpez.net/forums/d51943/php/langage/sessions/
* http://sebsauvage.net/wiki/doku.php?id=php:session
* http://sebsauvage.net/wiki/doku.php?id=php:shaarli
*
* Features:
* - Everything is stored on server-side (we do not trust client-side data,
* such as cookie expiration)
* - IP addresses + user agent are checked on each access to prevent session
* cookie hijacking (such as Firesheep)
* - Session expires on user inactivity (Session expiration date is
* automatically updated everytime the user accesses a page.)
* - A unique secret key is generated on server-side for this session
* (and never sent over the wire) which can be used
* to sign forms (HMAC) (See $_SESSION['uid'] )
* - Token management to prevent XSRF attacks.
*
* TODO:
* - log login fail
* - prevent brute force (ban IP)
*
* HOWTOUSE:
* - Just call Session::init(); to initialize session and
* check if connected with Session::isLogged()
*/
class Session
{
// If the user does not access any page within this time,
// his/her session is considered expired (in seconds).
public static $inactivity_timeout = 3600;
private static $_instance;
// constructor
private function __construct()
{
// Use cookies to store session.
ini_set('session.use_cookies', 1);
// Force cookies for session (phpsessionID forbidden in URL)
ini_set('session.use_only_cookies', 1);
if (!session_id()){
// Prevent php to use sessionID in URL if cookies are disabled.
ini_set('session.use_trans_sid', false);
session_start('poche');
}
}
// initialize session
public static function init()
{
if (!isset(self::$_instance)) {
self::$_instance = new Session();
}
}
// Returns the IP address, user agent and language of the client
// (Used to prevent session cookie hijacking.)
private static function _allInfos()
{
$infos = $_SERVER["REMOTE_ADDR"];
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$infos.=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
if (isset($_SERVER['HTTP_CLIENT_IP'])) {
$infos.='_'.$_SERVER['HTTP_CLIENT_IP'];
}
$infos.='_'.$_SERVER['HTTP_USER_AGENT'];
$infos.='_'.$_SERVER['HTTP_ACCEPT_LANGUAGE'];
return sha1($infos);
}
// Check that user/password is correct and init some SESSION variables.
public static function login($login,$password,$login_test,$password_test,
$pValues = array())
{
foreach ($pValues as $key => $value) {
$_SESSION[$key] = $value;
}
if ($login==$login_test && $password==$password_test){
// generate unique random number to sign forms (HMAC)
$_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand());
$_SESSION['info']=Session::_allInfos();
$_SESSION['username']=$login;
// Set session expiration.
$_SESSION['expires_on']=time()+Session::$inactivity_timeout;
return true;
}
return false;
}
// Force logout
public static function logout()
{
unset($_SESSION['uid'],$_SESSION['info'],$_SESSION['expires_on']);
}
// Make sure user is logged in.
public static function isLogged()
{
if (!isset ($_SESSION['uid'])
|| $_SESSION['info']!=Session::_allInfos()
|| time()>=$_SESSION['expires_on']){
Session::logout();
return false;
}
// User accessed a page : Update his/her session expiration date.
$_SESSION['expires_on']=time()+Session::$inactivity_timeout;
return true;
}
// Returns a token.
public static function getToken()
{
if (!isset($_SESSION['tokens'])){
$_SESSION['tokens']=array();
}
// We generate a random string and store it on the server side.
$rnd = sha1(uniqid('',true).'_'.mt_rand());
$_SESSION['tokens'][$rnd]=1;
return $rnd;
}
// Tells if a token is ok. Using this function will destroy the token.
// return true if token is ok.
public static function isToken($token)
{
if (isset($_SESSION['tokens'][$token]))
{
unset($_SESSION['tokens'][$token]); // Token is used: destroy it.
return true; // Token is ok.
}
return false; // Wrong token, or already used.
}
}

View file

@ -22,10 +22,12 @@ include 'functions.php';
require_once 'Readability.php'; require_once 'Readability.php';
require_once 'Encoding.php'; require_once 'Encoding.php';
require_once 'rain.tpl.class.php'; require_once 'rain.tpl.class.php';
require_once 'MyTool.class.php';
require_once 'Session.class.php';
$db = new db(DB_PATH); $db = new db(DB_PATH);
# Initialisation de RainTPL # initialisation de RainTPL
raintpl::$tpl_dir = './tpl/'; raintpl::$tpl_dir = './tpl/';
raintpl::$cache_dir = './cache/'; raintpl::$cache_dir = './cache/';
raintpl::$base_url = get_poche_url(); raintpl::$base_url = get_poche_url();
@ -33,13 +35,43 @@ raintpl::configure('path_replace', false);
raintpl::configure('debug', false); raintpl::configure('debug', false);
$tpl = new raintpl(); $tpl = new raintpl();
# Démarrage session et initialisation du jeton de sécurité # initialize session
session_start(); Session::init();
# XSRF protection with token
if (!empty($_POST)) {
if (!Session::isToken($_POST['token'])) {
die('Wrong token.');
}
unset($_SESSION['tokens']);
}
if (!isset($_SESSION['token_poche'])) { $ref = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'];
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token_poche'] = $token; if (isset($_GET['login'])) {
$_SESSION['token_time_poche'] = time(); // Login
if (!empty($_POST['login']) && !empty($_POST['password'])) {
if (Session::login('poche', 'poche', $_POST['login'], $_POST['password'])) {
if (!empty($_POST['longlastingsession'])) {
$_SESSION['longlastingsession'] = 31536000;
$_SESSION['expires_on'] = time() + $_SESSION['longlastingsession'];
session_set_cookie_params($_SESSION['longlastingsession']);
} else {
session_set_cookie_params(0); // when browser closes
}
session_regenerate_id(true);
MyTool::redirect();
}
logm('login failed');
die("Login failed !");
} else {
logm('login successful');
}
}
elseif (isset($_GET['logout'])) {
logm('logout');
Session::logout();
MyTool::redirect();
} }
# Traitement des paramètres et déclenchement des actions # Traitement des paramètres et déclenchement des actions
@ -48,8 +80,12 @@ $action = (isset ($_REQUEST['action'])) ? htmlentities($_REQUEST['ac
$_SESSION['sort'] = (isset ($_REQUEST['sort'])) ? htmlentities($_REQUEST['sort']) : 'id'; $_SESSION['sort'] = (isset ($_REQUEST['sort'])) ? htmlentities($_REQUEST['sort']) : 'id';
$id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : ''; $id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : '';
$url = (isset ($_GET['url'])) ? $_GET['url'] : ''; $url = (isset ($_GET['url'])) ? $_GET['url'] : '';
$token = (isset ($_REQUEST['token'])) ? $_REQUEST['token'] : '';
$tpl->assign('isLogged', Session::isLogged());
$tpl->assign('referer', $ref);
$tpl->assign('view', $view);
$tpl->assign('poche_url', get_poche_url());
if ($action != '') { if ($action != '') {
action_to_do($action, $url, $token, $id); action_to_do($action, $url, $id);
} }

View file

@ -91,7 +91,7 @@ function get_external_file($url)
function prepare_url($url) function prepare_url($url)
{ {
$parametres = array(); $parametres = array();
$url = html_entity_decode(trim($url)); $url = html_entity_decode(trim($url));
// We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...) // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...)
// from shaarli, by sebsauvage // from shaarli, by sebsauvage
@ -99,7 +99,7 @@ function prepare_url($url)
$i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i); $i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i);
$i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i); $i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i);
$title = $url; $title = $url;
if (!preg_match('!^https?://!i', $url)) if (!preg_match('!^https?://!i', $url))
$url = 'http://' . $url; $url = 'http://' . $url;
@ -230,7 +230,7 @@ function remove_directory($directory)
* Appel d'une action (mark as fav, archive, delete) * Appel d'une action (mark as fav, archive, delete)
*/ */
function action_to_do($action, $url, $token, $id = 0) function action_to_do($action, $url, $id = 0)
{ {
global $db; global $db;
@ -248,29 +248,20 @@ function action_to_do($action, $url, $token, $id = 0)
logm('add link ' . $url); logm('add link ' . $url);
break; break;
case 'delete': case 'delete':
if (verif_token($token)) { remove_directory(ABS_PATH . $id);
remove_directory(ABS_PATH . $id); $sql_action = "DELETE FROM entries WHERE id=?";
$sql_action = "DELETE FROM entries WHERE id=?"; $params_action = array($id);
$params_action = array($id); logm('delete link #' . $id);
logm('delete link #' . $id);
}
else logm('csrf problem while deleting entry');
break; break;
case 'toggle_fav' : case 'toggle_fav' :
if (verif_token($token)) { $sql_action = "UPDATE entries SET is_fav=~is_fav WHERE id=?";
$sql_action = "UPDATE entries SET is_fav=~is_fav WHERE id=?"; $params_action = array($id);
$params_action = array($id); logm('mark as favorite link #' . $id);
logm('mark as favorite link #' . $id);
}
else logm('csrf problem while fav entry');
break; break;
case 'toggle_archive' : case 'toggle_archive' :
if (verif_token($token)) { $sql_action = "UPDATE entries SET is_read=~is_read WHERE id=?";
$sql_action = "UPDATE entries SET is_read=~is_read WHERE id=?"; $params_action = array($id);
$params_action = array($id); logm('archive link #' . $id);
logm('archive link #' . $id);
}
else logm('csrf problem while archive entry');
break; break;
default: default:
break; break;
@ -305,7 +296,7 @@ function action_to_do($action, $url, $token, $id = 0)
/** /**
* Détermine quels liens afficher : home, fav ou archives * Détermine quels liens afficher : home, fav ou archives
*/ */
function display_view($view) function get_entries($view)
{ {
global $db; global $db;
@ -385,36 +376,6 @@ function get_article($id)
return $entry; return $entry;
} }
/**
* Vérifie si le jeton passé en $_POST correspond à celui en session
*/
function verif_token($token)
{
if(isset($_SESSION['token_poche']) && isset($_SESSION['token_time_poche']) && isset($token))
{
if($_SESSION['token_poche'] == $token)
{
$old_timestamp = time() - (15*60);
if($_SESSION['token_time_poche'] >= $old_timestamp)
{
return TRUE;
}
else {
session_destroy();
logm('session expired');
}
}
else {
logm('token error : the token is different');
return FALSE;
}
}
else {
logm('token error : the token is not here');
return FALSE;
}
}
function logm($message) function logm($message)
{ {
$t = strval(date('Y/m/d_H:i:s')).' - '.$_SERVER["REMOTE_ADDR"].' - '.strval($message)."\n"; $t = strval(date('Y/m/d_H:i:s')).' - '.$_SERVER["REMOTE_ADDR"].' - '.strval($message)."\n";

View file

@ -81,18 +81,18 @@ class RainTPL{
* *
*/ */
static $check_template_update = true; static $check_template_update = true;
/** /**
* PHP tags <? ?> * PHP tags <? ?>
* True: php tags are enabled into the template * True: php tags are enabled into the template
* False: php tags are disabled into the template and rendered as html * False: php tags are disabled into the template and rendered as html
* *
* @var bool * @var bool
*/ */
static $php_enabled = false; static $php_enabled = true;
/** /**
* Debug mode flag. * Debug mode flag.
* True: debug mode is used, syntax errors are displayed directly in template. Execution of script is not terminated. * True: debug mode is used, syntax errors are displayed directly in template. Execution of script is not terminated.
@ -285,7 +285,7 @@ class RainTPL{
*/ */
protected function xml_reSubstitution($capture) { protected function xml_reSubstitution($capture) {
return "<?php echo '<?xml ".stripslashes($capture[1])." ?>'; ?>"; return "<?php echo '<?xml ".stripslashes($capture[1])." ?>'; ?>";
} }
/** /**
* Compile and write the compiled template file * Compile and write the compiled template file
@ -304,11 +304,11 @@ class RainTPL{
$template_code = str_replace( array("<?","?>"), array("&lt;?","?&gt;"), $template_code ); $template_code = str_replace( array("<?","?>"), array("&lt;?","?&gt;"), $template_code );
//xml re-substitution //xml re-substitution
$template_code = preg_replace_callback ( "/##XML(.*?)XML##/s", array($this, 'xml_reSubstitution'), $template_code ); $template_code = preg_replace_callback ( "/##XML(.*?)XML##/s", array($this, 'xml_reSubstitution'), $template_code );
//compile template //compile template
$template_compiled = "<?php if(!class_exists('raintpl')){exit;}?>" . $this->compileTemplate( $template_code, $tpl_basedir ); $template_compiled = "<?php if(!class_exists('raintpl')){exit;}?>" . $this->compileTemplate( $template_code, $tpl_basedir );
// fix the php-eating-newline-after-closing-tag-problem // fix the php-eating-newline-after-closing-tag-problem
$template_compiled = str_replace( "?>\n", "?>\n\n", $template_compiled ); $template_compiled = str_replace( "?>\n", "?>\n\n", $template_compiled );
@ -413,7 +413,7 @@ class RainTPL{
// if the cache is active // if the cache is active
if( isset($code[ 2 ]) ){ if( isset($code[ 2 ]) ){
//dynamic include //dynamic include
$compiled_code .= '<?php $tpl = new '.get_class($this).';' . $compiled_code .= '<?php $tpl = new '.get_class($this).';' .
'if( $cache = $tpl->cache( $template = basename("'.$include_var.'") ) )' . 'if( $cache = $tpl->cache( $template = basename("'.$include_var.'") ) )' .
@ -426,7 +426,7 @@ class RainTPL{
'} ?>'; '} ?>';
} }
else{ else{
//dynamic include //dynamic include
$compiled_code .= '<?php $tpl = new '.get_class($this).';' . $compiled_code .= '<?php $tpl = new '.get_class($this).';' .
'$tpl_dir_temp = self::$tpl_dir;' . '$tpl_dir_temp = self::$tpl_dir;' .
@ -434,8 +434,8 @@ class RainTPL{
( !$loop_level ? null : '$tpl->assign( "key", $key'.$loop_level.' ); $tpl->assign( "value", $value'.$loop_level.' );' ). ( !$loop_level ? null : '$tpl->assign( "key", $key'.$loop_level.' ); $tpl->assign( "value", $value'.$loop_level.' );' ).
'$tpl->draw( dirname("'.$include_var.'") . ( substr("'.$include_var.'",-1,1) != "/" ? "/" : "" ) . basename("'.$include_var.'") );'. '$tpl->draw( dirname("'.$include_var.'") . ( substr("'.$include_var.'",-1,1) != "/" ? "/" : "" ) . basename("'.$include_var.'") );'.
'?>'; '?>';
} }
} }
@ -548,7 +548,7 @@ class RainTPL{
else else
// parse the function // parse the function
$parsed_function = $function . $this->var_replace( $code[ 2 ], $tag_left_delimiter = null, $tag_right_delimiter = null, $php_left_delimiter = null, $php_right_delimiter = null, $loop_level ); $parsed_function = $function . $this->var_replace( $code[ 2 ], $tag_left_delimiter = null, $tag_right_delimiter = null, $php_left_delimiter = null, $php_right_delimiter = null, $loop_level );
//if code //if code
$compiled_code .= "<?php echo $parsed_function; ?>"; $compiled_code .= "<?php echo $parsed_function; ?>";
} }
@ -582,8 +582,8 @@ class RainTPL{
} }
return $compiled_code; return $compiled_code;
} }
/** /**
* Reduce a path, eg. www/library/../filepath//file => www/filepath/file * Reduce a path, eg. www/library/../filepath//file => www/filepath/file
* @param type $path * @param type $path
@ -612,7 +612,7 @@ class RainTPL{
if( self::$path_replace ){ if( self::$path_replace ){
$tpl_dir = self::$base_url . self::$tpl_dir . $tpl_basedir; $tpl_dir = self::$base_url . self::$tpl_dir . $tpl_basedir;
// reduce the path // reduce the path
$path = $this->reduce_path($tpl_dir); $path = $this->reduce_path($tpl_dir);
@ -683,7 +683,7 @@ class RainTPL{
$this->function_check( $tag ); $this->function_check( $tag );
$extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level ); $extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level );
// check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value
$is_init_variable = preg_match( "/^(\s*?)\=[^=](.*?)$/", $extra_var ); $is_init_variable = preg_match( "/^(\s*?)\=[^=](.*?)$/", $extra_var );
@ -712,7 +712,7 @@ class RainTPL{
//if there's a function //if there's a function
if( $function_var ){ if( $function_var ){
// check if there's a function or a static method and separate, function by parameters // check if there's a function or a static method and separate, function by parameters
$function_var = str_replace("::", "@double_dot@", $function_var ); $function_var = str_replace("::", "@double_dot@", $function_var );
@ -786,7 +786,7 @@ class RainTPL{
// check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value
$is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var ); $is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var );
//function associate to variable //function associate to variable
$function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null; $function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null;
@ -805,16 +805,16 @@ class RainTPL{
//transform .$variable in ["$variable"] and .variable in ["variable"] //transform .$variable in ["$variable"] and .variable in ["variable"]
$variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path ); $variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path );
// if is an assignment also assign the variable to $this->var['value'] // if is an assignment also assign the variable to $this->var['value']
if( $is_init_variable ) if( $is_init_variable )
$extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var; $extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var;
//if there's a function //if there's a function
if( $function_var ){ if( $function_var ){
// check if there's a function or a static method and separate, function by parameters // check if there's a function or a static method and separate, function by parameters
$function_var = str_replace("::", "@double_dot@", $function_var ); $function_var = str_replace("::", "@double_dot@", $function_var );
@ -855,13 +855,13 @@ class RainTPL{
$php_var = '$' . $var_name . $variable_path; $php_var = '$' . $var_name . $variable_path;
}else }else
$php_var = '$' . $var_name . $variable_path; $php_var = '$' . $var_name . $variable_path;
// compile the variable for php // compile the variable for php
if( isset( $function ) ) if( isset( $function ) )
$php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter; $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter;
else else
$php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter; $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter;
$html = str_replace( $tag, $php_var, $html ); $html = str_replace( $tag, $php_var, $html );

View file

@ -10,17 +10,19 @@
include dirname(__FILE__).'/inc/config.php'; include dirname(__FILE__).'/inc/config.php';
$entries = display_view($view); $entries = get_entries($view);
$tpl->assign('title', 'poche, a read it later open source system'); $tpl->assign('title', 'poche, a read it later open source system');
$tpl->assign('view', $view);
$tpl->assign('poche_url', get_poche_url());
$tpl->assign('entries', $entries); $tpl->assign('entries', $entries);
$tpl->assign('load_all_js', 1); $tpl->assign('load_all_js', 1);
$tpl->assign('token', $_SESSION['token_poche']);
$tpl->draw('head'); $tpl->draw('head');
$tpl->draw('home'); if (Session::isLogged()) {
$tpl->draw('entries'); $tpl->draw('home');
$tpl->draw('js'); $tpl->draw('entries');
$tpl->draw('footer'); $tpl->draw('js');
}
else {
$tpl->draw('login');
}
$tpl->draw('footer');

View file

@ -6,9 +6,9 @@
</h2> </h2>
<div class="tools"> <div class="tools">
<ul> <ul>
<li><a title="toggle mark as read" class="tool archive {if="$value.is_read == '0'"}archive-off{/if}" onclick="toggle_archive(this, {$value.id}, '{$token}')"><span></span></a></li> <li><a title="toggle mark as read" class="tool archive {if="$value.is_read == '0'"}archive-off{/if}" onclick="toggle_archive(this, {$value.id}, '<?php echo Session::getToken(); ?>')"><span></span></a></li>
<li><a title="toggle favorite" class="tool fav {if="$value.is_fav == '0'"}fav-off{/if}" onclick="toggle_favorite(this, {$value.id}, '{$token}')"><span></span></a></li> <li><a title="toggle favorite" class="tool fav {if="$value.is_fav == '0'"}fav-off{/if}" onclick="toggle_favorite(this, {$value.id}, '<?php echo Session::getToken(); ?>')"><span></span></a></li>
<li><form method="post" onsubmit="return confirm('Are you sure?')" style="display: inline;"><input type="hidden" name="token" id="token" value="{$token}" /><input type="hidden" id="action" name="action" value="delete" /><input type="hidden" id="id" name="id" value="{$value.id}" /><input type="submit" class="delete" title="toggle delete" /></form></li> <li><form method="post" onsubmit="return confirm('Are you sure?')" style="display: inline;"><input type="hidden" name="token" id="token" value="<?php echo Session::getToken(); ?>" /><input type="hidden" id="action" name="action" value="delete" /><input type="hidden" id="id" name="id" value="{$value.id}" /><input type="submit" class="delete" title="toggle delete" /></form></li>
</ul> </ul>
</div> </div>
</span> </span>

View file

@ -15,4 +15,9 @@
<link rel="apple-touch-icon-precomposed" href="./img/apple-touch-icon-precomposed.png"> <link rel="apple-touch-icon-precomposed" href="./img/apple-touch-icon-precomposed.png">
<link rel="stylesheet" href="./css/knacss.css" media="all"> <link rel="stylesheet" href="./css/knacss.css" media="all">
<link rel="stylesheet" href="./css/style.css" media="all"> <link rel="stylesheet" href="./css/style.css" media="all">
</head> </head>
<body>
<header>
<h1><img src="./img/logo.png" alt="logo poche" />poche</h1>
</header>
<div id="main">

View file

@ -1,16 +1,12 @@
<body>
<header>
<h1><img src="./img/logo.png" alt="logo poche" />poche</h1>
</header>
<div id="main">
<ul id="links"> <ul id="links">
<li><a href="index.php" {if="$view == 'index'"}class="current"{/if}>home</a></li> <li><a href="index.php" {if="$view == 'index'"}class="current"{/if}>home</a></li>
<li><a href="?view=fav" {if="$view == 'fav'"}class="current"{/if}>favorites</a></li> <li><a href="?view=fav" {if="$view == 'fav'"}class="current"{/if}>favorites</a></li>
<li><a href="?view=archive" {if="$view == 'archive'"}class="current"{/if}>archive</a></li> <li><a href="?view=archive" {if="$view == 'archive'"}class="current"{/if}>archive</a></li>
<li><a style="cursor: move" title="i am a bookmarklet, use me !" href="javascript:(function(){var%20url%20=%20location.href%20||%20url;window.open('{$poche_url}?action=add&url='%20+%20encodeURIComponent(url),'_self');})();">poche it !</a></li> <li><a style="cursor: move" title="i am a bookmarklet, use me !" href="javascript:(function(){var%20url%20=%20location.href%20||%20url;window.open('{$poche_url}?action=add&url='%20+%20encodeURIComponent(url),'_self');})();">poche it !</a></li>
<li><a href="?logout" title="Logout">logout</a></li>
</ul> </ul>
<ul id="sort"> <ul id="sort">
<li><img src="img/up.png" onclick="sort_links('{$view}', 'ia', '{$token}');" title="by date asc" /> by date <img src="img/down.png" onclick="sort_links('{$view}', 'id', '{$token}');" title="by date desc" /></li> <li><img src="img/up.png" onclick="sort_links('{$view}', 'ia', '{'<?php echo Session::getToken(); ?>'}');" title="by date asc" /> by date <img src="img/down.png" onclick="sort_links('{$view}', 'id', '<?php echo Session::getToken(); ?>');" title="by date desc" /></li>
<li><img src="img/up.png" onclick="sort_links('{$view}', 'ta', '{$token}');" title="by title asc" /> by title <img src="img/down.png" onclick="sort_links('{$view}', 'td', '{$token}');" title="by title desc" /></li> <li><img src="img/up.png" onclick="sort_links('{$view}', 'ta', '<?php echo Session::getToken(); ?>');" title="by title asc" /> by title <img src="img/down.png" onclick="sort_links('{$view}', 'td', '<?php echo Session::getToken(); ?>');" title="by title desc" /></li>
</ul> </ul>
<div id="content"> <div id="content">

13
tpl/login.html Normal file
View file

@ -0,0 +1,13 @@
<form method="post" action="?login" name="loginform">
<fieldset>
<h2>login to your poche</h2>
<ul id="login">
<li><label for="login">Login</label> <input type="text" id="login" name="login" placeholder="Login" tabindex="1"></li>
<li><label for="password">Password</label> <input type="password" id="password" name="password" placeholder="Password" tabindex="2"></li>
<li><label><input type="checkbox" name="longlastingsession" tabindex="3">&nbsp;Stay signed in (Do not check on public computers)</label></li>
<li><button type="submit" tabindex="4">Sign in</button></li>
</ul>
</fieldset>
<input type="hidden" name="returnurl" value="<?php echo htmlspecialchars($referer);?>">
<input type="hidden" name="token" value="<?php echo Session::getToken(); ?>">
</form>

View file

@ -1,4 +1,21 @@
{include="head"} <!DOCTYPE html>
<!--[if lte IE 6]> <html class="no-js ie6 ie67 ie678" lang="en"> <![endif]-->
<!--[if lte IE 7]> <html class="no-js ie7 ie67 ie678" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 ie678" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=10">
<title>{$title}</title>
<link rel="shortcut icon" type="image/x-icon" href="./img/favicon.ico" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="./img/apple-touch-icon-144x144-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="./img/apple-touch-icon-72x72-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="./img/apple-touch-icon-precomposed.png">
<link rel="stylesheet" href="./css/knacss.css" media="all">
<link rel="stylesheet" href="./css/style.css" media="all">
</head>
<body class="article"> <body class="article">
<div id="article" class="w600p"> <div id="article" class="w600p">
<div class="backhome"> <div class="backhome">
@ -6,9 +23,9 @@
</div> </div>
<div class="tools"> <div class="tools">
<ul> <ul>
<li><a title="toggle mark as read" class="tool archive {if="$is_read == '0'"}archive-off{/if}" onclick="toggle_archive(this, {$id}, '{$token}')"><span></span></a></li> <li><a title="toggle mark as read" class="tool archive {if="$is_read == '0'"}archive-off{/if}" onclick="toggle_archive(this, {$id}, '<?php echo Session::getToken(); ?>')"><span></span></a></li>
<li><a title="toggle favorite" class="tool fav {if="$is_fav == '0'"}fav-off{/if}" onclick="toggle_favorite(this, {$id}, '{$token}')"><span></span></a></li> <li><a title="toggle favorite" class="tool fav {if="$is_fav == '0'"}fav-off{/if}" onclick="toggle_favorite(this, {$id}, '<?php echo Session::getToken(); ?>')"><span></span></a></li>
<li><form method="post" onsubmit="return confirm('Are you sure?')" style="display: inline;" action="index.php"><input type="hidden" name="token" id="token" value="{$token}" /><input type="hidden" id="action" name="action" value="delete" /><input type="hidden" id="id" name="id" value="{$id}" /><input type="submit" class="delete" title="toggle delete" /></form></li> <li><form method="post" onsubmit="return confirm('Are you sure?')" style="display: inline;" action="index.php"><input type="hidden" name="token" id="token" value="<?php echo Session::getToken(); ?>" /><input type="hidden" id="action" name="action" value="delete" /><input type="hidden" id="id" name="id" value="{$id}" /><input type="submit" class="delete" title="toggle delete" /></form></li>
</ul> </ul>
</div> </div>
<header class="mbm"> <header class="mbm">
@ -25,7 +42,12 @@
<a href="index.php" title="back to home">&larr;</a> <a href="index.php" title="back to home">&larr;</a>
</div> </div>
</div> </div>
{include="footer"}
{include="js"} {include="js"}
<footer class="mr2 mt3 smaller">
<p>powered by <a href="http://inthepoche.com">poche</a><br />follow us on <a href="https://twitter.com/getpoche" title="follow us on twitter">twitter</a></p>
</footer>
</body> </body>
</html> </html>

View file

@ -24,7 +24,6 @@ if(!empty($id)) {
$tpl->assign('is_fav', $entry[0]['is_fav']); $tpl->assign('is_fav', $entry[0]['is_fav']);
$tpl->assign('is_read', $entry[0]['is_read']); $tpl->assign('is_read', $entry[0]['is_read']);
$tpl->assign('load_all_js', 0); $tpl->assign('load_all_js', 0);
$tpl->assign('token', $_SESSION['token_poche']);
$tpl->draw('view'); $tpl->draw('view');
} }
else { else {