aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornicosomb <nicolas@loeuillet.org>2013-04-18 15:39:34 +0200
committernicosomb <nicolas@loeuillet.org>2013-04-18 15:39:34 +0200
commite4d2565e05a517641de921c4c19a2c9d1beea2e7 (patch)
tree156715bc739b2810368c717f20f03172955c32a1
parentb693a19e1c3d4ffcf2f3aaef1d67df4b986e4903 (diff)
downloadwallabag-e4d2565e05a517641de921c4c19a2c9d1beea2e7.tar.gz
wallabag-e4d2565e05a517641de921c4c19a2c9d1beea2e7.tar.zst
wallabag-e4d2565e05a517641de921c4c19a2c9d1beea2e7.zip
#4 - ajout système de connexion (login poche mot de passe poche pour l'instant)
-rw-r--r--CREDITS1
-rw-r--r--css/style.css11
-rw-r--r--import.php2
-rw-r--r--inc/MyTool.class.php256
-rw-r--r--inc/Session.class.php136
-rw-r--r--inc/config.php54
-rw-r--r--inc/functions.php67
-rw-r--r--inc/rain.tpl.class.php46
-rw-r--r--index.php18
-rw-r--r--tpl/entries.html6
-rw-r--r--tpl/head.html7
-rw-r--r--tpl/home.html10
-rw-r--r--tpl/login.html13
-rw-r--r--tpl/view.html34
-rw-r--r--view.php1
15 files changed, 544 insertions, 118 deletions
diff --git a/CREDITS b/CREDITS
index 31e74bad..c917a012 100644
--- a/CREDITS
+++ b/CREDITS
@@ -5,6 +5,7 @@ poche is based on :
5* logo by Brightmix http://www.iconfinder.com/icondetails/43256/128/jeans_monotone_pocket_icon 5* logo by Brightmix http://www.iconfinder.com/icondetails/43256/128/jeans_monotone_pocket_icon
6* icons http://icomoon.io 6* icons http://icomoon.io
7* PHP Simple HTML DOM Parser (for Pocket import) http://simplehtmldom.sourceforge.net/ 7* PHP Simple HTML DOM Parser (for Pocket import) http://simplehtmldom.sourceforge.net/
8* Session https://github.com/tontof/kriss_feed/blob/master/src/class/Session.php
8 9
9poche is developed by Nicolas Lœuillet under the Do What the Fuck You Want to Public License 10poche is developed by Nicolas Lœuillet under the Do What the Fuck You Want to Public License
10 11
diff --git a/css/style.css b/css/style.css
index cf1ee2f0..29dca289 100644
--- a/css/style.css
+++ b/css/style.css
@@ -62,17 +62,16 @@ header {
62 color: #F1F1F1; 62 color: #F1F1F1;
63} 63}
64 64
65/*#content {
66 width: 800px;
67 margin: 0 auto;
68}*/
69
70
71footer { 65footer {
72 text-align: right; 66 text-align: right;
73} 67}
74 68
75/*** ***/ 69/*** ***/
70/*** LOGIN FORM ***/
71ul#login li {
72 list-style-type: none;
73}
74/*** ***/
76/*** LINKS DISPLAY ***/ 75/*** LINKS DISPLAY ***/
77 76
78#main a.tool { 77#main a.tool {
diff --git a/import.php b/import.php
index 135443c9..72e3eac7 100644
--- a/import.php
+++ b/import.php
@@ -30,7 +30,7 @@ else {
30 $url = $a[0]->href; 30 $url = $a[0]->href;
31 31
32 32
33 action_to_do('add', $url, $token); 33 action_to_do('add', $url);
34 if ($read == '1') { 34 if ($read == '1') {
35 $last_id = $db->getHandle()->lastInsertId(); 35 $last_id = $db->getHandle()->lastInsertId();
36 $sql_update = "UPDATE entries SET is_read=~is_read WHERE id=?"; 36 $sql_update = "UPDATE entries SET is_read=~is_read WHERE id=?";
diff --git a/inc/MyTool.class.php b/inc/MyTool.class.php
new file mode 100644
index 00000000..8206f3f7
--- /dev/null
+++ b/inc/MyTool.class.php
@@ -0,0 +1,256 @@
1<?php
2class MyTool
3{
4 public static function initPhp()
5 {
6 define('START_TIME', microtime(true));
7
8 if (phpversion() < 5) {
9 die("Argh you don't have PHP 5 !");
10 }
11
12 error_reporting(E_ALL);
13
14 function stripslashesDeep($value) {
15 return is_array($value)
16 ? array_map('stripslashesDeep', $value)
17 : stripslashes($value);
18 }
19
20 if (get_magic_quotes_gpc()) {
21 $_POST = array_map('stripslashesDeep', $_POST);
22 $_GET = array_map('stripslashesDeep', $_GET);
23 $_COOKIE = array_map('stripslashesDeep', $_COOKIE);
24 }
25
26 ob_start();
27 register_shutdown_function('ob_end_flush');
28 }
29
30 public static function isUrl($url)
31 {
32 // http://neo22s.com/check-if-url-exists-and-is-online-php/
33 $pattern='|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i';
34
35 return preg_match($pattern, $url);
36 }
37
38 public static function isEmail($email)
39 {
40 $pattern = "/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2, 4}$/i";
41
42 return (preg_match($pattern, $email));
43 }
44
45 public static function formatBBCode($text)
46 {
47 $replace = array(
48 '/\[m\](.+?)\[\/m\]/is'
49 => '/* moderate */',
50 '/\[b\](.+?)\[\/b\]/is'
51 => '<strong>$1</strong>',
52 '/\[i\](.+?)\[\/i\]/is'
53 => '<em>$1</em>',
54 '/\[s\](.+?)\[\/s\]/is'
55 => '<del>$1</del>',
56 '/\[u\](.+?)\[\/u\]/is'
57 => '<span style="text-decoration: underline;">$1</span>',
58 '/\[url\](.+?)\[\/url]/is'
59 => '<a href="$1">$1</a>',
60 '/\[url=(\w+:\/\/[^\]]+)\](.+?)\[\/url]/is'
61 => '<a href="$1">$2</a>',
62 '/\[quote\](.+?)\[\/quote\]/is'
63 => '<blockquote>$1</blockquote>',
64 '/\[code\](.+?)\[\/code\]/is'
65 => '<code>$1</code>',
66 '/\[([^[]+)\|([^[]+)\]/is'
67 => '<a href="$2">$1</a>'
68 );
69 $text = preg_replace(
70 array_keys($replace),
71 array_values($replace),
72 $text
73 );
74
75 return $text;
76 }
77
78 public static function formatText($text)
79 {
80 $text = preg_replace_callback(
81 '/<code_html>(.*?)<\/code_html>/is',
82 create_function(
83 '$matches',
84 'return htmlspecialchars($matches[1]);'
85 ),
86 $text
87 );
88 $text = preg_replace_callback(
89 '/<code_php>(.*?)<\/code_php>/is',
90 create_function(
91 '$matches',
92 'return highlight_string("<?php $matches[1] ?>", true);'
93 ),
94 $text
95 );
96 $text = preg_replace('/<br \/>/is', '', $text);
97
98 $text = preg_replace(
99 '#(^|\s)([a-z]+://([^\s\w/]?[\w/])*)(\s|$)#im',
100 '\\1<a href="\\2">\\2</a>\\4',
101 $text
102 );
103 $text = preg_replace(
104 '#(^|\s)wp:?([a-z]{2}|):([\w]+)#im',
105 '\\1<a href="http://\\2.wikipedia.org/wiki/\\3">\\3</a>',
106 $text
107 );
108 $text = str_replace(
109 'http://.wikipedia.org/wiki/',
110 'http://www.wikipedia.org/wiki/',
111 $text
112 );
113 $text = str_replace('\wp:', 'wp:', $text);
114 $text = str_replace('\http:', 'http:', $text);
115 $text = MyTool::formatBBCode($text);
116 $text = nl2br($text);
117
118 return $text;
119 }
120
121 public static function getUrl()
122 {
123 $https = (!empty($_SERVER['HTTPS'])
124 && (strtolower($_SERVER['HTTPS']) == 'on'))
125 || (isset($_SERVER["SERVER_PORT"])
126 && $_SERVER["SERVER_PORT"] == '443'); // HTTPS detection.
127 $serverport = (!isset($_SERVER["SERVER_PORT"])
128 || $_SERVER["SERVER_PORT"] == '80'
129 || ($https && $_SERVER["SERVER_PORT"] == '443')
130 ? ''
131 : ':' . $_SERVER["SERVER_PORT"]);
132
133 $scriptname = str_replace('/index.php', '/', $_SERVER["SCRIPT_NAME"]);
134
135 if (!isset($_SERVER["SERVER_NAME"])) {
136 return $scriptname;
137 }
138
139 return 'http' . ($https ? 's' : '') . '://'
140 . $_SERVER["SERVER_NAME"] . $serverport . $scriptname;
141 }
142
143 public static function rrmdir($dir)
144 {
145 if (is_dir($dir) && ($d = @opendir($dir))) {
146 while (($file = @readdir($d)) !== false) {
147 if ( $file == '.' || $file == '..' ) {
148 continue;
149 } else {
150 unlink($dir . '/' . $file);
151 }
152 }
153 }
154 }
155
156 public static function humanBytes($bytes)
157 {
158 $siPrefix = array( 'bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB' );
159 $base = 1024;
160 $class = min((int) log($bytes, $base), count($siPrefix) - 1);
161 $val = sprintf('%1.2f', $bytes / pow($base, $class));
162
163 return $val . ' ' . $siPrefix[$class];
164 }
165
166 public static function returnBytes($val)
167 {
168 $val = trim($val);
169 $last = strtolower($val[strlen($val)-1]);
170 switch($last)
171 {
172 case 'g': $val *= 1024;
173 case 'm': $val *= 1024;
174 case 'k': $val *= 1024;
175 }
176
177 return $val;
178 }
179
180 public static function getMaxFileSize()
181 {
182 $sizePostMax = MyTool::returnBytes(ini_get('post_max_size'));
183 $sizeUploadMax = MyTool::returnBytes(ini_get('upload_max_filesize'));
184
185 // Return the smaller of two:
186 return min($sizePostMax, $sizeUploadMax);
187 }
188
189 public static function smallHash($text)
190 {
191 $t = rtrim(base64_encode(hash('crc32', $text, true)), '=');
192 // Get rid of characters which need encoding in URLs.
193 $t = str_replace('+', '-', $t);
194 $t = str_replace('/', '_', $t);
195 $t = str_replace('=', '@', $t);
196
197 return $t;
198 }
199
200 public static function renderJson($data)
201 {
202 header('Cache-Control: no-cache, must-revalidate');
203 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
204 header('Content-type: application/json; charset=UTF-8');
205
206 echo json_encode($data);
207 exit();
208 }
209
210 public static function grabToLocal($url, $file, $force = false)
211 {
212 if ((!file_exists($file) || $force) && in_array('curl', get_loaded_extensions())){
213 $ch = curl_init ($url);
214 curl_setopt($ch, CURLOPT_HEADER, false);
215 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
216 curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
217 $raw = curl_exec($ch);
218 if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) {
219 $fp = fopen($file, 'x');
220 fwrite($fp, $raw);
221 fclose($fp);
222 }
223 curl_close ($ch);
224 }
225 }
226
227 public static function redirect($rurl = '')
228 {
229 if ($rurl === '') {
230 // if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['SERVER_NAME'])==0)
231 $rurl = (empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']);
232 if (isset($_POST['returnurl'])) {
233 $rurl = $_POST['returnurl'];
234 }
235 }
236
237 // prevent loop
238 if (empty($rurl) || parse_url($rurl, PHP_URL_QUERY) === $_SERVER['QUERY_STRING']) {
239 $rurl = MyTool::getUrl();
240 }
241
242 if (substr($rurl, 0, 1) !== '?') {
243 $ref = MyTool::getUrl();
244 if (substr($rurl, 0, strlen($ref)) !== $ref) {
245 $rurl = $ref;
246 }
247 }
248 header('Location: '.$rurl);
249 exit();
250 }
251
252 public static function silence_errors($num, $str)
253 {
254// No-op
255 }
256} \ No newline at end of file
diff --git a/inc/Session.class.php b/inc/Session.class.php
new file mode 100644
index 00000000..06fa6a8e
--- /dev/null
+++ b/inc/Session.class.php
@@ -0,0 +1,136 @@
1<?php
2/**
3 * Session management class
4 * http://www.developpez.net/forums/d51943/php/langage/sessions/
5 * http://sebsauvage.net/wiki/doku.php?id=php:session
6 * http://sebsauvage.net/wiki/doku.php?id=php:shaarli
7 *
8 * Features:
9 * - Everything is stored on server-side (we do not trust client-side data,
10 * such as cookie expiration)
11 * - IP addresses + user agent are checked on each access to prevent session
12 * cookie hijacking (such as Firesheep)
13 * - Session expires on user inactivity (Session expiration date is
14 * automatically updated everytime the user accesses a page.)
15 * - A unique secret key is generated on server-side for this session
16 * (and never sent over the wire) which can be used
17 * to sign forms (HMAC) (See $_SESSION['uid'] )
18 * - Token management to prevent XSRF attacks.
19 *
20 * TODO:
21 * - log login fail
22 * - prevent brute force (ban IP)
23 *
24 * HOWTOUSE:
25 * - Just call Session::init(); to initialize session and
26 * check if connected with Session::isLogged()
27 */
28
29class Session
30{
31 // If the user does not access any page within this time,
32 // his/her session is considered expired (in seconds).
33 public static $inactivity_timeout = 3600;
34 private static $_instance;
35
36 // constructor
37 private function __construct()
38 {
39 // Use cookies to store session.
40 ini_set('session.use_cookies', 1);
41 // Force cookies for session (phpsessionID forbidden in URL)
42 ini_set('session.use_only_cookies', 1);
43 if (!session_id()){
44 // Prevent php to use sessionID in URL if cookies are disabled.
45 ini_set('session.use_trans_sid', false);
46 session_start('poche');
47 }
48 }
49
50 // initialize session
51 public static function init()
52 {
53 if (!isset(self::$_instance)) {
54 self::$_instance = new Session();
55 }
56 }
57
58 // Returns the IP address, user agent and language of the client
59 // (Used to prevent session cookie hijacking.)
60 private static function _allInfos()
61 {
62 $infos = $_SERVER["REMOTE_ADDR"];
63 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
64 $infos.=$_SERVER['HTTP_X_FORWARDED_FOR'];
65 }
66 if (isset($_SERVER['HTTP_CLIENT_IP'])) {
67 $infos.='_'.$_SERVER['HTTP_CLIENT_IP'];
68 }
69 $infos.='_'.$_SERVER['HTTP_USER_AGENT'];
70 $infos.='_'.$_SERVER['HTTP_ACCEPT_LANGUAGE'];
71 return sha1($infos);
72 }
73
74 // Check that user/password is correct and init some SESSION variables.
75 public static function login($login,$password,$login_test,$password_test,
76 $pValues = array())
77 {
78 foreach ($pValues as $key => $value) {
79 $_SESSION[$key] = $value;
80 }
81 if ($login==$login_test && $password==$password_test){
82 // generate unique random number to sign forms (HMAC)
83 $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand());
84 $_SESSION['info']=Session::_allInfos();
85 $_SESSION['username']=$login;
86 // Set session expiration.
87 $_SESSION['expires_on']=time()+Session::$inactivity_timeout;
88 return true;
89 }
90 return false;
91 }
92
93 // Force logout
94 public static function logout()
95 {
96 unset($_SESSION['uid'],$_SESSION['info'],$_SESSION['expires_on']);
97 }
98
99 // Make sure user is logged in.
100 public static function isLogged()
101 {
102 if (!isset ($_SESSION['uid'])
103 || $_SESSION['info']!=Session::_allInfos()
104 || time()>=$_SESSION['expires_on']){
105 Session::logout();
106 return false;
107 }
108 // User accessed a page : Update his/her session expiration date.
109 $_SESSION['expires_on']=time()+Session::$inactivity_timeout;
110 return true;
111 }
112
113 // Returns a token.
114 public static function getToken()
115 {
116 if (!isset($_SESSION['tokens'])){
117 $_SESSION['tokens']=array();
118 }
119 // We generate a random string and store it on the server side.
120 $rnd = sha1(uniqid('',true).'_'.mt_rand());
121 $_SESSION['tokens'][$rnd]=1;
122 return $rnd;
123 }
124
125 // Tells if a token is ok. Using this function will destroy the token.
126 // return true if token is ok.
127 public static function isToken($token)
128 {
129 if (isset($_SESSION['tokens'][$token]))
130 {
131 unset($_SESSION['tokens'][$token]); // Token is used: destroy it.
132 return true; // Token is ok.
133 }
134 return false; // Wrong token, or already used.
135 }
136} \ No newline at end of file
diff --git a/inc/config.php b/inc/config.php
index 386fd036..403217ce 100644
--- a/inc/config.php
+++ b/inc/config.php
@@ -22,10 +22,12 @@ include 'functions.php';
22require_once 'Readability.php'; 22require_once 'Readability.php';
23require_once 'Encoding.php'; 23require_once 'Encoding.php';
24require_once 'rain.tpl.class.php'; 24require_once 'rain.tpl.class.php';
25require_once 'MyTool.class.php';
26require_once 'Session.class.php';
25 27
26$db = new db(DB_PATH); 28$db = new db(DB_PATH);
27 29
28# Initialisation de RainTPL 30# initialisation de RainTPL
29raintpl::$tpl_dir = './tpl/'; 31raintpl::$tpl_dir = './tpl/';
30raintpl::$cache_dir = './cache/'; 32raintpl::$cache_dir = './cache/';
31raintpl::$base_url = get_poche_url(); 33raintpl::$base_url = get_poche_url();
@@ -33,13 +35,43 @@ raintpl::configure('path_replace', false);
33raintpl::configure('debug', false); 35raintpl::configure('debug', false);
34$tpl = new raintpl(); 36$tpl = new raintpl();
35 37
36# Démarrage session et initialisation du jeton de sécurité 38# initialize session
37session_start(); 39Session::init();
40# XSRF protection with token
41if (!empty($_POST)) {
42 if (!Session::isToken($_POST['token'])) {
43 die('Wrong token.');
44 }
45 unset($_SESSION['tokens']);
46}
47
48$ref = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'];
49
50if (isset($_GET['login'])) {
51 // Login
52 if (!empty($_POST['login']) && !empty($_POST['password'])) {
53 if (Session::login('poche', 'poche', $_POST['login'], $_POST['password'])) {
54 if (!empty($_POST['longlastingsession'])) {
55 $_SESSION['longlastingsession'] = 31536000;
56 $_SESSION['expires_on'] = time() + $_SESSION['longlastingsession'];
57 session_set_cookie_params($_SESSION['longlastingsession']);
58 } else {
59 session_set_cookie_params(0); // when browser closes
60 }
61 session_regenerate_id(true);
38 62
39if (!isset($_SESSION['token_poche'])) { 63 MyTool::redirect();
40 $token = md5(uniqid(rand(), TRUE)); 64 }
41 $_SESSION['token_poche'] = $token; 65 logm('login failed');
42 $_SESSION['token_time_poche'] = time(); 66 die("Login failed !");
67 } else {
68 logm('login successful');
69 }
70}
71elseif (isset($_GET['logout'])) {
72 logm('logout');
73 Session::logout();
74 MyTool::redirect();
43} 75}
44 76
45# Traitement des paramètres et déclenchement des actions 77# Traitement des paramètres et déclenchement des actions
@@ -48,8 +80,12 @@ $action = (isset ($_REQUEST['action'])) ? htmlentities($_REQUEST['ac
48$_SESSION['sort'] = (isset ($_REQUEST['sort'])) ? htmlentities($_REQUEST['sort']) : 'id'; 80$_SESSION['sort'] = (isset ($_REQUEST['sort'])) ? htmlentities($_REQUEST['sort']) : 'id';
49$id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : ''; 81$id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : '';
50$url = (isset ($_GET['url'])) ? $_GET['url'] : ''; 82$url = (isset ($_GET['url'])) ? $_GET['url'] : '';
51$token = (isset ($_REQUEST['token'])) ? $_REQUEST['token'] : ''; 83
84$tpl->assign('isLogged', Session::isLogged());
85$tpl->assign('referer', $ref);
86$tpl->assign('view', $view);
87$tpl->assign('poche_url', get_poche_url());
52 88
53if ($action != '') { 89if ($action != '') {
54 action_to_do($action, $url, $token, $id); 90 action_to_do($action, $url, $id);
55} 91}
diff --git a/inc/functions.php b/inc/functions.php
index 936ec6ea..13acd36f 100644
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -91,7 +91,7 @@ function get_external_file($url)
91function prepare_url($url) 91function prepare_url($url)
92{ 92{
93 $parametres = array(); 93 $parametres = array();
94 $url = html_entity_decode(trim($url)); 94 $url = html_entity_decode(trim($url));
95 95
96 // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...) 96 // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...)
97 // from shaarli, by sebsauvage 97 // from shaarli, by sebsauvage
@@ -99,7 +99,7 @@ function prepare_url($url)
99 $i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i); 99 $i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i);
100 $i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i); 100 $i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i);
101 101
102 $title = $url; 102 $title = $url;
103 if (!preg_match('!^https?://!i', $url)) 103 if (!preg_match('!^https?://!i', $url))
104 $url = 'http://' . $url; 104 $url = 'http://' . $url;
105 105
@@ -230,7 +230,7 @@ function remove_directory($directory)
230 * Appel d'une action (mark as fav, archive, delete) 230 * Appel d'une action (mark as fav, archive, delete)
231 */ 231 */
232 232
233function action_to_do($action, $url, $token, $id = 0) 233function action_to_do($action, $url, $id = 0)
234{ 234{
235 global $db; 235 global $db;
236 236
@@ -248,29 +248,20 @@ function action_to_do($action, $url, $token, $id = 0)
248 logm('add link ' . $url); 248 logm('add link ' . $url);
249 break; 249 break;
250 case 'delete': 250 case 'delete':
251 if (verif_token($token)) { 251 remove_directory(ABS_PATH . $id);
252 remove_directory(ABS_PATH . $id); 252 $sql_action = "DELETE FROM entries WHERE id=?";
253 $sql_action = "DELETE FROM entries WHERE id=?"; 253 $params_action = array($id);
254 $params_action = array($id); 254 logm('delete link #' . $id);
255 logm('delete link #' . $id);
256 }
257 else logm('csrf problem while deleting entry');
258 break; 255 break;
259 case 'toggle_fav' : 256 case 'toggle_fav' :
260 if (verif_token($token)) { 257 $sql_action = "UPDATE entries SET is_fav=~is_fav WHERE id=?";
261 $sql_action = "UPDATE entries SET is_fav=~is_fav WHERE id=?"; 258 $params_action = array($id);
262 $params_action = array($id); 259 logm('mark as favorite link #' . $id);
263 logm('mark as favorite link #' . $id);
264 }
265 else logm('csrf problem while fav entry');
266 break; 260 break;
267 case 'toggle_archive' : 261 case 'toggle_archive' :
268 if (verif_token($token)) { 262 $sql_action = "UPDATE entries SET is_read=~is_read WHERE id=?";
269 $sql_action = "UPDATE entries SET is_read=~is_read WHERE id=?"; 263 $params_action = array($id);
270 $params_action = array($id); 264 logm('archive link #' . $id);
271 logm('archive link #' . $id);
272 }
273 else logm('csrf problem while archive entry');
274 break; 265 break;
275 default: 266 default:
276 break; 267 break;
@@ -305,7 +296,7 @@ function action_to_do($action, $url, $token, $id = 0)
305/** 296/**
306 * Détermine quels liens afficher : home, fav ou archives 297 * Détermine quels liens afficher : home, fav ou archives
307 */ 298 */
308function display_view($view) 299function get_entries($view)
309{ 300{
310 global $db; 301 global $db;
311 302
@@ -385,36 +376,6 @@ function get_article($id)
385 return $entry; 376 return $entry;
386} 377}
387 378
388/**
389 * Vérifie si le jeton passé en $_POST correspond à celui en session
390 */
391function verif_token($token)
392{
393 if(isset($_SESSION['token_poche']) && isset($_SESSION['token_time_poche']) && isset($token))
394 {
395 if($_SESSION['token_poche'] == $token)
396 {
397 $old_timestamp = time() - (15*60);
398 if($_SESSION['token_time_poche'] >= $old_timestamp)
399 {
400 return TRUE;
401 }
402 else {
403 session_destroy();
404 logm('session expired');
405 }
406 }
407 else {
408 logm('token error : the token is different');
409 return FALSE;
410 }
411 }
412 else {
413 logm('token error : the token is not here');
414 return FALSE;
415 }
416}
417
418function logm($message) 379function logm($message)
419{ 380{
420 $t = strval(date('Y/m/d_H:i:s')).' - '.$_SERVER["REMOTE_ADDR"].' - '.strval($message)."\n"; 381 $t = strval(date('Y/m/d_H:i:s')).' - '.$_SERVER["REMOTE_ADDR"].' - '.strval($message)."\n";
diff --git a/inc/rain.tpl.class.php b/inc/rain.tpl.class.php
index ea83b2c1..6522c798 100644
--- a/inc/rain.tpl.class.php
+++ b/inc/rain.tpl.class.php
@@ -81,18 +81,18 @@ class RainTPL{
81 * 81 *
82 */ 82 */
83 static $check_template_update = true; 83 static $check_template_update = true;
84 84
85 85
86 /** 86 /**
87 * PHP tags <? ?> 87 * PHP tags <? ?>
88 * True: php tags are enabled into the template 88 * True: php tags are enabled into the template
89 * False: php tags are disabled into the template and rendered as html 89 * False: php tags are disabled into the template and rendered as html
90 * 90 *
91 * @var bool 91 * @var bool
92 */ 92 */
93 static $php_enabled = false; 93 static $php_enabled = true;
94
94 95
95
96 /** 96 /**
97 * Debug mode flag. 97 * Debug mode flag.
98 * True: debug mode is used, syntax errors are displayed directly in template. Execution of script is not terminated. 98 * True: debug mode is used, syntax errors are displayed directly in template. Execution of script is not terminated.
@@ -285,7 +285,7 @@ class RainTPL{
285 */ 285 */
286 protected function xml_reSubstitution($capture) { 286 protected function xml_reSubstitution($capture) {
287 return "<?php echo '<?xml ".stripslashes($capture[1])." ?>'; ?>"; 287 return "<?php echo '<?xml ".stripslashes($capture[1])." ?>'; ?>";
288 } 288 }
289 289
290 /** 290 /**
291 * Compile and write the compiled template file 291 * Compile and write the compiled template file
@@ -304,11 +304,11 @@ class RainTPL{
304 $template_code = str_replace( array("<?","?>"), array("&lt;?","?&gt;"), $template_code ); 304 $template_code = str_replace( array("<?","?>"), array("&lt;?","?&gt;"), $template_code );
305 305
306 //xml re-substitution 306 //xml re-substitution
307 $template_code = preg_replace_callback ( "/##XML(.*?)XML##/s", array($this, 'xml_reSubstitution'), $template_code ); 307 $template_code = preg_replace_callback ( "/##XML(.*?)XML##/s", array($this, 'xml_reSubstitution'), $template_code );
308 308
309 //compile template 309 //compile template
310 $template_compiled = "<?php if(!class_exists('raintpl')){exit;}?>" . $this->compileTemplate( $template_code, $tpl_basedir ); 310 $template_compiled = "<?php if(!class_exists('raintpl')){exit;}?>" . $this->compileTemplate( $template_code, $tpl_basedir );
311 311
312 312
313 // fix the php-eating-newline-after-closing-tag-problem 313 // fix the php-eating-newline-after-closing-tag-problem
314 $template_compiled = str_replace( "?>\n", "?>\n\n", $template_compiled ); 314 $template_compiled = str_replace( "?>\n", "?>\n\n", $template_compiled );
@@ -413,7 +413,7 @@ class RainTPL{
413 413
414 // if the cache is active 414 // if the cache is active
415 if( isset($code[ 2 ]) ){ 415 if( isset($code[ 2 ]) ){
416 416
417 //dynamic include 417 //dynamic include
418 $compiled_code .= '<?php $tpl = new '.get_class($this).';' . 418 $compiled_code .= '<?php $tpl = new '.get_class($this).';' .
419 'if( $cache = $tpl->cache( $template = basename("'.$include_var.'") ) )' . 419 'if( $cache = $tpl->cache( $template = basename("'.$include_var.'") ) )' .
@@ -426,7 +426,7 @@ class RainTPL{
426 '} ?>'; 426 '} ?>';
427 } 427 }
428 else{ 428 else{
429 429
430 //dynamic include 430 //dynamic include
431 $compiled_code .= '<?php $tpl = new '.get_class($this).';' . 431 $compiled_code .= '<?php $tpl = new '.get_class($this).';' .
432 '$tpl_dir_temp = self::$tpl_dir;' . 432 '$tpl_dir_temp = self::$tpl_dir;' .
@@ -434,8 +434,8 @@ class RainTPL{
434 ( !$loop_level ? null : '$tpl->assign( "key", $key'.$loop_level.' ); $tpl->assign( "value", $value'.$loop_level.' );' ). 434 ( !$loop_level ? null : '$tpl->assign( "key", $key'.$loop_level.' ); $tpl->assign( "value", $value'.$loop_level.' );' ).
435 '$tpl->draw( dirname("'.$include_var.'") . ( substr("'.$include_var.'",-1,1) != "/" ? "/" : "" ) . basename("'.$include_var.'") );'. 435 '$tpl->draw( dirname("'.$include_var.'") . ( substr("'.$include_var.'",-1,1) != "/" ? "/" : "" ) . basename("'.$include_var.'") );'.
436 '?>'; 436 '?>';
437 437
438 438
439 } 439 }
440 440
441 } 441 }
@@ -548,7 +548,7 @@ class RainTPL{
548 else 548 else
549 // parse the function 549 // parse the function
550 $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 ); 550 $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 );
551 551
552 //if code 552 //if code
553 $compiled_code .= "<?php echo $parsed_function; ?>"; 553 $compiled_code .= "<?php echo $parsed_function; ?>";
554 } 554 }
@@ -582,8 +582,8 @@ class RainTPL{
582 } 582 }
583 return $compiled_code; 583 return $compiled_code;
584 } 584 }
585 585
586 586
587 /** 587 /**
588 * Reduce a path, eg. www/library/../filepath//file => www/filepath/file 588 * Reduce a path, eg. www/library/../filepath//file => www/filepath/file
589 * @param type $path 589 * @param type $path
@@ -612,7 +612,7 @@ class RainTPL{
612 if( self::$path_replace ){ 612 if( self::$path_replace ){
613 613
614 $tpl_dir = self::$base_url . self::$tpl_dir . $tpl_basedir; 614 $tpl_dir = self::$base_url . self::$tpl_dir . $tpl_basedir;
615 615
616 // reduce the path 616 // reduce the path
617 $path = $this->reduce_path($tpl_dir); 617 $path = $this->reduce_path($tpl_dir);
618 618
@@ -683,7 +683,7 @@ class RainTPL{
683 $this->function_check( $tag ); 683 $this->function_check( $tag );
684 684
685 $extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level ); 685 $extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level );
686 686
687 687
688 // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value 688 // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value
689 $is_init_variable = preg_match( "/^(\s*?)\=[^=](.*?)$/", $extra_var ); 689 $is_init_variable = preg_match( "/^(\s*?)\=[^=](.*?)$/", $extra_var );
@@ -712,7 +712,7 @@ class RainTPL{
712 712
713 //if there's a function 713 //if there's a function
714 if( $function_var ){ 714 if( $function_var ){
715 715
716 // check if there's a function or a static method and separate, function by parameters 716 // check if there's a function or a static method and separate, function by parameters
717 $function_var = str_replace("::", "@double_dot@", $function_var ); 717 $function_var = str_replace("::", "@double_dot@", $function_var );
718 718
@@ -786,7 +786,7 @@ class RainTPL{
786 786
787 // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value 787 // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value
788 $is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var ); 788 $is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var );
789 789
790 //function associate to variable 790 //function associate to variable
791 $function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null; 791 $function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null;
792 792
@@ -805,16 +805,16 @@ class RainTPL{
805 805
806 //transform .$variable in ["$variable"] and .variable in ["variable"] 806 //transform .$variable in ["$variable"] and .variable in ["variable"]
807 $variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path ); 807 $variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path );
808 808
809 // if is an assignment also assign the variable to $this->var['value'] 809 // if is an assignment also assign the variable to $this->var['value']
810 if( $is_init_variable ) 810 if( $is_init_variable )
811 $extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var; 811 $extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var;
812 812
813 813
814 814
815 //if there's a function 815 //if there's a function
816 if( $function_var ){ 816 if( $function_var ){
817 817
818 // check if there's a function or a static method and separate, function by parameters 818 // check if there's a function or a static method and separate, function by parameters
819 $function_var = str_replace("::", "@double_dot@", $function_var ); 819 $function_var = str_replace("::", "@double_dot@", $function_var );
820 820
@@ -855,13 +855,13 @@ class RainTPL{
855 $php_var = '$' . $var_name . $variable_path; 855 $php_var = '$' . $var_name . $variable_path;
856 }else 856 }else
857 $php_var = '$' . $var_name . $variable_path; 857 $php_var = '$' . $var_name . $variable_path;
858 858
859 // compile the variable for php 859 // compile the variable for php
860 if( isset( $function ) ) 860 if( isset( $function ) )
861 $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter; 861 $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter;
862 else 862 else
863 $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter; 863 $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter;
864 864
865 $html = str_replace( $tag, $php_var, $html ); 865 $html = str_replace( $tag, $php_var, $html );
866 866
867 867
diff --git a/index.php b/index.php
index d0d008ed..995426b4 100644
--- a/index.php
+++ b/index.php
@@ -10,17 +10,19 @@
10 10
11include dirname(__FILE__).'/inc/config.php'; 11include dirname(__FILE__).'/inc/config.php';
12 12
13$entries = display_view($view); 13$entries = get_entries($view);
14 14
15$tpl->assign('title', 'poche, a read it later open source system'); 15$tpl->assign('title', 'poche, a read it later open source system');
16$tpl->assign('view', $view);
17$tpl->assign('poche_url', get_poche_url());
18$tpl->assign('entries', $entries); 16$tpl->assign('entries', $entries);
19$tpl->assign('load_all_js', 1); 17$tpl->assign('load_all_js', 1);
20$tpl->assign('token', $_SESSION['token_poche']);
21 18
22$tpl->draw('head'); 19$tpl->draw('head');
23$tpl->draw('home'); 20if (Session::isLogged()) {
24$tpl->draw('entries'); 21 $tpl->draw('home');
25$tpl->draw('js'); 22 $tpl->draw('entries');
26$tpl->draw('footer'); 23 $tpl->draw('js');
24}
25else {
26 $tpl->draw('login');
27}
28$tpl->draw('footer'); \ No newline at end of file
diff --git a/tpl/entries.html b/tpl/entries.html
index 0d3e6bc0..c74bc346 100644
--- a/tpl/entries.html
+++ b/tpl/entries.html
@@ -6,9 +6,9 @@
6 </h2> 6 </h2>
7 <div class="tools"> 7 <div class="tools">
8 <ul> 8 <ul>
9 <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> 9 <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>
10 <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> 10 <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>
11 <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> 11 <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>
12 </ul> 12 </ul>
13 </div> 13 </div>
14 </span> 14 </span>
diff --git a/tpl/head.html b/tpl/head.html
index 66150d8f..6fcf9741 100644
--- a/tpl/head.html
+++ b/tpl/head.html
@@ -15,4 +15,9 @@
15 <link rel="apple-touch-icon-precomposed" href="./img/apple-touch-icon-precomposed.png"> 15 <link rel="apple-touch-icon-precomposed" href="./img/apple-touch-icon-precomposed.png">
16 <link rel="stylesheet" href="./css/knacss.css" media="all"> 16 <link rel="stylesheet" href="./css/knacss.css" media="all">
17 <link rel="stylesheet" href="./css/style.css" media="all"> 17 <link rel="stylesheet" href="./css/style.css" media="all">
18 </head> \ No newline at end of file 18 </head>
19 <body>
20 <header>
21 <h1><img src="./img/logo.png" alt="logo poche" />poche</h1>
22 </header>
23 <div id="main"> \ No newline at end of file
diff --git a/tpl/home.html b/tpl/home.html
index 568b9274..216f39b9 100644
--- a/tpl/home.html
+++ b/tpl/home.html
@@ -1,16 +1,12 @@
1 <body>
2 <header>
3 <h1><img src="./img/logo.png" alt="logo poche" />poche</h1>
4 </header>
5 <div id="main">
6 <ul id="links"> 1 <ul id="links">
7 <li><a href="index.php" {if="$view == 'index'"}class="current"{/if}>home</a></li> 2 <li><a href="index.php" {if="$view == 'index'"}class="current"{/if}>home</a></li>
8 <li><a href="?view=fav" {if="$view == 'fav'"}class="current"{/if}>favorites</a></li> 3 <li><a href="?view=fav" {if="$view == 'fav'"}class="current"{/if}>favorites</a></li>
9 <li><a href="?view=archive" {if="$view == 'archive'"}class="current"{/if}>archive</a></li> 4 <li><a href="?view=archive" {if="$view == 'archive'"}class="current"{/if}>archive</a></li>
10 <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> 5 <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>
6 <li><a href="?logout" title="Logout">logout</a></li>
11 </ul> 7 </ul>
12 <ul id="sort"> 8 <ul id="sort">
13 <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> 9 <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>
14 <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> 10 <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>
15 </ul> 11 </ul>
16 <div id="content"> \ No newline at end of file 12 <div id="content"> \ No newline at end of file
diff --git a/tpl/login.html b/tpl/login.html
new file mode 100644
index 00000000..024b3fd0
--- /dev/null
+++ b/tpl/login.html
@@ -0,0 +1,13 @@
1 <form method="post" action="?login" name="loginform">
2 <fieldset>
3 <h2>login to your poche</h2>
4 <ul id="login">
5 <li><label for="login">Login</label> <input type="text" id="login" name="login" placeholder="Login" tabindex="1"></li>
6 <li><label for="password">Password</label> <input type="password" id="password" name="password" placeholder="Password" tabindex="2"></li>
7 <li><label><input type="checkbox" name="longlastingsession" tabindex="3">&nbsp;Stay signed in (Do not check on public computers)</label></li>
8 <li><button type="submit" tabindex="4">Sign in</button></li>
9 </ul>
10 </fieldset>
11 <input type="hidden" name="returnurl" value="<?php echo htmlspecialchars($referer);?>">
12 <input type="hidden" name="token" value="<?php echo Session::getToken(); ?>">
13 </form> \ No newline at end of file
diff --git a/tpl/view.html b/tpl/view.html
index 3a1ba7c6..1191bd82 100644
--- a/tpl/view.html
+++ b/tpl/view.html
@@ -1,4 +1,21 @@
1{include="head"} 1<!DOCTYPE html>
2<!--[if lte IE 6]> <html class="no-js ie6 ie67 ie678" lang="en"> <![endif]-->
3<!--[if lte IE 7]> <html class="no-js ie7 ie67 ie678" lang="en"> <![endif]-->
4<!--[if IE 8]> <html class="no-js ie8 ie678" lang="en"> <![endif]-->
5<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
6<html>
7 <head>
8 <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
9 <meta charset="utf-8">
10 <meta http-equiv="X-UA-Compatible" content="IE=10">
11 <title>{$title}</title>
12 <link rel="shortcut icon" type="image/x-icon" href="./img/favicon.ico" />
13 <link rel="apple-touch-icon-precomposed" sizes="144x144" href="./img/apple-touch-icon-144x144-precomposed.png">
14 <link rel="apple-touch-icon-precomposed" sizes="72x72" href="./img/apple-touch-icon-72x72-precomposed.png">
15 <link rel="apple-touch-icon-precomposed" href="./img/apple-touch-icon-precomposed.png">
16 <link rel="stylesheet" href="./css/knacss.css" media="all">
17 <link rel="stylesheet" href="./css/style.css" media="all">
18 </head>
2 <body class="article"> 19 <body class="article">
3 <div id="article" class="w600p"> 20 <div id="article" class="w600p">
4 <div class="backhome"> 21 <div class="backhome">
@@ -6,9 +23,9 @@
6 </div> 23 </div>
7 <div class="tools"> 24 <div class="tools">
8 <ul> 25 <ul>
9 <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> 26 <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>
10 <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> 27 <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>
11 <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> 28 <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>
12 </ul> 29 </ul>
13 </div> 30 </div>
14 <header class="mbm"> 31 <header class="mbm">
@@ -25,7 +42,12 @@
25 <a href="index.php" title="back to home">&larr;</a> 42 <a href="index.php" title="back to home">&larr;</a>
26 </div> 43 </div>
27 </div> 44 </div>
28 {include="footer"} 45
29 {include="js"} 46 {include="js"}
47
48 <footer class="mr2 mt3 smaller">
49 <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>
50 </footer>
51
30 </body> 52 </body>
31</html> 53</html> \ No newline at end of file
diff --git a/view.php b/view.php
index 9ba6f62d..29a5b324 100644
--- a/view.php
+++ b/view.php
@@ -24,7 +24,6 @@ if(!empty($id)) {
24 $tpl->assign('is_fav', $entry[0]['is_fav']); 24 $tpl->assign('is_fav', $entry[0]['is_fav']);
25 $tpl->assign('is_read', $entry[0]['is_read']); 25 $tpl->assign('is_read', $entry[0]['is_read']);
26 $tpl->assign('load_all_js', 0); 26 $tpl->assign('load_all_js', 0);
27 $tpl->assign('token', $_SESSION['token_poche']);
28 $tpl->draw('view'); 27 $tpl->draw('view');
29 } 28 }
30 else { 29 else {