diff options
-rw-r--r-- | css/style.css | 50 | ||||
-rw-r--r-- | inc/config.php | 10 | ||||
-rwxr-xr-x | inc/functions.php | 30 | ||||
-rwxr-xr-x | index.php | 13 | ||||
-rw-r--r-- | js/poche.js | 8 | ||||
-rw-r--r-- | process.php | 45 | ||||
-rw-r--r-- | tpl/home.html | 10 | ||||
-rwxr-xr-x | tpl/view.html | 8 | ||||
-rwxr-xr-x | view.php | 1 |
9 files changed, 125 insertions, 50 deletions
diff --git a/css/style.css b/css/style.css index 959a411a..d77fb9e7 100644 --- a/css/style.css +++ b/css/style.css | |||
@@ -65,6 +65,16 @@ footer { | |||
65 | cursor: pointer; | 65 | cursor: pointer; |
66 | } | 66 | } |
67 | 67 | ||
68 | input[type=submit].delete { | ||
69 | background : url('../img/delete.png') no-repeat center center; | ||
70 | width : 16px; | ||
71 | height :16px; | ||
72 | border : none; | ||
73 | color : transparent; | ||
74 | cursor: pointer; | ||
75 | font-size : 0; | ||
76 | } | ||
77 | |||
68 | #main #content { | 78 | #main #content { |
69 | margin-top: 20px; | 79 | margin-top: 20px; |
70 | } | 80 | } |
@@ -77,13 +87,15 @@ footer { | |||
77 | min-height: 8em; | 87 | min-height: 8em; |
78 | -webkit-border-radius: 2px; | 88 | -webkit-border-radius: 2px; |
79 | border-radius: 2px; | 89 | border-radius: 2px; |
80 | -webkit-box-shadow: 0px 0px 2px -1px #000; | 90 | -webkit-box-shadow: 0px 0px 6px -1px #000; |
81 | box-shadow: 0px 0px 2px -1px #000; | 91 | box-shadow: 0px 0px 6px -1px #000; |
82 | width: 30%; | 92 | width: 30%; |
83 | margin: 10px; | 93 | margin: 10px; |
84 | float: left; | 94 | float: left; |
85 | } | 95 | } |
86 | 96 | #main .entrie h2 { | |
97 | width: 95%; | ||
98 | } | ||
87 | #main .entrie h2 a { | 99 | #main .entrie h2 a { |
88 | text-decoration: none; | 100 | text-decoration: none; |
89 | } | 101 | } |
@@ -92,20 +104,38 @@ footer { | |||
92 | color: #F5BE00; | 104 | color: #F5BE00; |
93 | } | 105 | } |
94 | 106 | ||
95 | #main .entrie .tools { | 107 | .tools { |
96 | position:absolute; | 108 | position: absolute; |
97 | bottom: 0; | 109 | top: 20px; |
98 | width: 100%; | 110 | right: 20px; |
111 | width: 30px; | ||
99 | text-align: right; | 112 | text-align: right; |
100 | margin-left: -20px; | 113 | } |
114 | |||
115 | .tools ul { | ||
116 | padding: 0; margin: 0; | ||
117 | list-style-type: none; | ||
118 | } | ||
119 | |||
120 | .tools ul li { | ||
121 | line-height: 20px; | ||
122 | } | ||
123 | |||
124 | .tools a.tool { | ||
125 | cursor: pointer; | ||
101 | } | 126 | } |
102 | 127 | ||
103 | #article .tools { | 128 | #article .tools { |
129 | position: relative; | ||
104 | display: inline; | 130 | display: inline; |
131 | top: 0px; | ||
132 | right: 0px; | ||
133 | width: 100%; | ||
134 | text-align: left; | ||
105 | } | 135 | } |
106 | 136 | ||
107 | #article .tools a.tool { | 137 | #article.tools ul li{ |
108 | cursor: pointer; | 138 | display: inline; |
109 | } | 139 | } |
110 | 140 | ||
111 | #main .entrie .tools a.tool span, #article .tools a.tool span { | 141 | #main .entrie .tools a.tool span, #article .tools a.tool span { |
diff --git a/inc/config.php b/inc/config.php index 29a22507..84b86998 100644 --- a/inc/config.php +++ b/inc/config.php | |||
@@ -22,4 +22,12 @@ raintpl::$cache_dir = './cache/'; | |||
22 | raintpl::$base_url = get_poche_url(); | 22 | raintpl::$base_url = get_poche_url(); |
23 | raintpl::configure('path_replace', false); | 23 | raintpl::configure('path_replace', false); |
24 | raintpl::configure('debug', false); | 24 | raintpl::configure('debug', false); |
25 | $tpl = new raintpl(); \ No newline at end of file | 25 | $tpl = new raintpl(); |
26 | |||
27 | session_start(); | ||
28 | |||
29 | if (!isset($_SESSION['token_poche'])) { | ||
30 | $token = md5(uniqid(rand(), TRUE)); | ||
31 | $_SESSION['token_poche'] = $token; | ||
32 | $_SESSION['token_time_poche'] = time(); | ||
33 | } \ No newline at end of file | ||
diff --git a/inc/functions.php b/inc/functions.php index 45828bf2..30e00393 100755 --- a/inc/functions.php +++ b/inc/functions.php | |||
@@ -125,7 +125,7 @@ function prepare_url($url) | |||
125 | /** | 125 | /** |
126 | * Appel d'une action (mark as fav, archive, delete) | 126 | * Appel d'une action (mark as fav, archive, delete) |
127 | */ | 127 | */ |
128 | function action_to_do($action, $id) | 128 | function action_to_do($action, $id, $url, $token) |
129 | { | 129 | { |
130 | global $db; | 130 | global $db; |
131 | 131 | ||
@@ -140,8 +140,11 @@ function action_to_do($action, $id) | |||
140 | $params_action = array($url, $parametres_url['title'], $parametres_url['content']); | 140 | $params_action = array($url, $parametres_url['title'], $parametres_url['content']); |
141 | break; | 141 | break; |
142 | case 'delete': | 142 | case 'delete': |
143 | $sql_action = "DELETE FROM entries WHERE id=?"; | 143 | if (verif_token($token)) { |
144 | $params_action = array($id); | 144 | $sql_action = "DELETE FROM entries WHERE id=?"; |
145 | $params_action = array($id); | ||
146 | } | ||
147 | else die('CSRF problem'); | ||
145 | break; | 148 | break; |
146 | default: | 149 | default: |
147 | break; | 150 | break; |
@@ -224,4 +227,25 @@ function get_article($id) | |||
224 | } | 227 | } |
225 | 228 | ||
226 | return $entry; | 229 | return $entry; |
230 | } | ||
231 | |||
232 | /** | ||
233 | * Vérifie si le jeton passé en $_POST correspond à celui en session | ||
234 | */ | ||
235 | function verif_token($token) | ||
236 | { | ||
237 | if(isset($_SESSION['token_poche']) && isset($_SESSION['token_time_poche']) && isset($token)) | ||
238 | { | ||
239 | if($_SESSION['token_poche'] == $token) | ||
240 | { | ||
241 | $old_timestamp = time() - (15*60); | ||
242 | if($_SESSION['token_time_poche'] >= $old_timestamp) | ||
243 | { | ||
244 | return TRUE; | ||
245 | } | ||
246 | else return FALSE; | ||
247 | } | ||
248 | else return FALSE; | ||
249 | } | ||
250 | else return FALSE; | ||
227 | } \ No newline at end of file | 251 | } \ No newline at end of file |
@@ -10,12 +10,16 @@ | |||
10 | 10 | ||
11 | include dirname(__FILE__).'/inc/config.php'; | 11 | include dirname(__FILE__).'/inc/config.php'; |
12 | 12 | ||
13 | $action = (isset ($_GET['action'])) ? htmlspecialchars($_GET['action']) : ''; | 13 | $action = (isset ($_REQUEST['action'])) ? htmlentities($_REQUEST['action']) : ''; |
14 | $view = (isset ($_GET['view'])) ? htmlspecialchars($_GET['view']) : 'index'; | 14 | $view = (isset ($_GET['view'])) ? htmlentities($_GET['view']) : 'index'; |
15 | $id = (isset ($_GET['id'])) ? htmlspecialchars($_GET['id']) : ''; | 15 | $id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : ''; |
16 | $url = (isset ($_GET['url'])) ? $_GET['url'] : ''; | 16 | $url = (isset ($_GET['url'])) ? $_GET['url'] : ''; |
17 | $token = (isset ($_POST['token'])) ? $_POST['token'] : ''; | ||
18 | |||
19 | if ($action != '') { | ||
20 | action_to_do($action, $id, $url, $token); | ||
21 | } | ||
17 | 22 | ||
18 | action_to_do($action, $id); | ||
19 | $entries = display_view($view); | 23 | $entries = display_view($view); |
20 | 24 | ||
21 | $tpl->assign('title', 'poche, a read it later open source system'); | 25 | $tpl->assign('title', 'poche, a read it later open source system'); |
@@ -23,4 +27,5 @@ $tpl->assign('view', $view); | |||
23 | $tpl->assign('poche_url', get_poche_url()); | 27 | $tpl->assign('poche_url', get_poche_url()); |
24 | $tpl->assign('entries', $entries); | 28 | $tpl->assign('entries', $entries); |
25 | $tpl->assign('load_all_js', 1); | 29 | $tpl->assign('load_all_js', 1); |
30 | $tpl->assign('token', $_SESSION['token_poche']); | ||
26 | $tpl->draw('home'); \ No newline at end of file | 31 | $tpl->draw('home'); \ No newline at end of file |
diff --git a/js/poche.js b/js/poche.js index 64df553c..0dcc0a35 100644 --- a/js/poche.js +++ b/js/poche.js | |||
@@ -1,16 +1,16 @@ | |||
1 | function toggle_favorite(element, id) { | 1 | function toggle_favorite(element, id, token) { |
2 | $(element).toggleClass('fav-off'); | 2 | $(element).toggleClass('fav-off'); |
3 | $.ajax ({ | 3 | $.ajax ({ |
4 | url: "process.php?action=toggle_fav", | 4 | url: "process.php?action=toggle_fav", |
5 | data:{id:id} | 5 | data:{id:id, token:token} |
6 | }); | 6 | }); |
7 | } | 7 | } |
8 | 8 | ||
9 | function toggle_archive(element, id, view_article) { | 9 | function toggle_archive(element, id, token, view_article) { |
10 | $(element).toggleClass('archive-off'); | 10 | $(element).toggleClass('archive-off'); |
11 | $.ajax ({ | 11 | $.ajax ({ |
12 | url: "process.php?action=toggle_archive", | 12 | url: "process.php?action=toggle_archive", |
13 | data:{id:id} | 13 | data:{id:id, token:token} |
14 | }); | 14 | }); |
15 | var obj = $('#entry-'+id); | 15 | var obj = $('#entry-'+id); |
16 | 16 | ||
diff --git a/process.php b/process.php index 0bd20e5d..5a056caa 100644 --- a/process.php +++ b/process.php | |||
@@ -11,27 +11,30 @@ | |||
11 | include dirname(__FILE__).'/inc/config.php'; | 11 | include dirname(__FILE__).'/inc/config.php'; |
12 | $db = new db(DB_PATH); | 12 | $db = new db(DB_PATH); |
13 | 13 | ||
14 | $action = (isset ($_GET['action'])) ? htmlspecialchars($_GET['action']) : ''; | 14 | $action = (isset ($_GET['action'])) ? htmlentities($_GET['action']) : ''; |
15 | $id = (isset ($_GET['id'])) ? htmlspecialchars($_GET['id']) : ''; | 15 | $id = (isset ($_GET['id'])) ? htmlentities($_GET['id']) : ''; |
16 | $token = (isset ($_GET['token'])) ? $_GET['token'] : ''; | ||
16 | 17 | ||
17 | switch ($action) | 18 | if (verif_token($token)) { |
18 | { | 19 | switch ($action) |
19 | case 'toggle_fav' : | 20 | { |
20 | $sql_action = "UPDATE entries SET is_fav=~is_fav WHERE id=?"; | 21 | case 'toggle_fav' : |
21 | $params_action = array($id); | 22 | $sql_action = "UPDATE entries SET is_fav=~is_fav WHERE id=?"; |
22 | break; | 23 | $params_action = array($id); |
23 | case 'toggle_archive' : | 24 | break; |
24 | $sql_action = "UPDATE entries SET is_read=~is_read WHERE id=?"; | 25 | case 'toggle_archive' : |
25 | $params_action = array($id); | 26 | $sql_action = "UPDATE entries SET is_read=~is_read WHERE id=?"; |
26 | break; | 27 | $params_action = array($id); |
27 | default: | 28 | break; |
28 | break; | 29 | default: |
29 | } | 30 | break; |
31 | } | ||
30 | 32 | ||
31 | # action query | 33 | # action query |
32 | if (isset($sql_action)) | 34 | if (isset($sql_action)) |
33 | { | 35 | { |
34 | $query = $db->getHandle()->prepare($sql_action); | 36 | $query = $db->getHandle()->prepare($sql_action); |
35 | $query->execute($params_action); | 37 | $query->execute($params_action); |
38 | } | ||
36 | } | 39 | } |
37 | ?> \ No newline at end of file | 40 | else die('CSRF problem'); \ No newline at end of file |
diff --git a/tpl/home.html b/tpl/home.html index 70a35a7f..0de8007b 100644 --- a/tpl/home.html +++ b/tpl/home.html | |||
@@ -8,7 +8,7 @@ | |||
8 | <li><a href="index.php" {if="$view == 'index'"}class="current"{/if}>home</a></li> | 8 | <li><a href="index.php" {if="$view == 'index'"}class="current"{/if}>home</a></li> |
9 | <li><a href="?view=fav" {if="$view == 'fav'"}class="current"{/if}>favorites</a></li> | 9 | <li><a href="?view=fav" {if="$view == 'fav'"}class="current"{/if}>favorites</a></li> |
10 | <li><a href="?view=archive" {if="$view == 'archive'"}class="current"{/if}>archive</a></li> | 10 | <li><a href="?view=archive" {if="$view == 'archive'"}class="current"{/if}>archive</a></li> |
11 | <li><a style="cursor: move" title="i am a bookmarklet, use me !" href="javascript:(function(){var%20url%20=%20location.href;var%20title%20=%20document.title%20||%20url;window.open('{$poche_url}?action=add&url='%20+%20encodeURIComponent(url),'_self');})();">poche it !</a></li> | 11 | <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> |
12 | </ul> | 12 | </ul> |
13 | <div id="content"> | 13 | <div id="content"> |
14 | {loop="entries"} | 14 | {loop="entries"} |
@@ -18,9 +18,11 @@ | |||
18 | <a href="view.php?id={$value.id}">{$value.title}</a> | 18 | <a href="view.php?id={$value.id}">{$value.title}</a> |
19 | </h2> | 19 | </h2> |
20 | <div class="tools"> | 20 | <div class="tools"> |
21 | <a title="toggle mark as read" class="tool archive {if="$value.is_read == '0'"}archive-off{/if}" onclick="toggle_archive(this, {$value.id})"><span></span></a> | 21 | <ul> |
22 | <a title="toggle favorite" class="tool fav {if="$value.is_fav == '0'"}fav-off{/if}" onclick="toggle_favorite(this, {$value.id})"><span></span></a> | 22 | <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> |
23 | <a href="?action=delete&id={$value.id}" title="toggle delete" onclick="return confirm('Are you sure?')" class="tool delete"><span></span></a> | 23 | <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> |
24 | <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> | ||
25 | </ul> | ||
24 | </div> | 26 | </div> |
25 | </span> | 27 | </span> |
26 | </div> | 28 | </div> |
diff --git a/tpl/view.html b/tpl/view.html index 1e057889..d24d26ed 100755 --- a/tpl/view.html +++ b/tpl/view.html | |||
@@ -5,9 +5,11 @@ | |||
5 | <a href="index.php" title="back to home">←</a> | 5 | <a href="index.php" title="back to home">←</a> |
6 | </div> | 6 | </div> |
7 | <div class="tools"> | 7 | <div class="tools"> |
8 | <a title="toggle mark as read" class="tool archive {if="$is_read == 0"}archive-off{/if}" onclick="toggle_archive(this, {$id}, 1)"><span></span></a> | 8 | <ul> |
9 | <a title="toggle favorite" class="tool fav {if="$is_fav == 0"}fav-off{/if}" onclick="toggle_favorite(this, {$id})"><span></span></a> | 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> |
10 | <a href="index.php?action=delete&id={$id}" title="toggle delete" onclick="return confirm('Are you sure?')" class="tool delete"><span></span></a> | 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> |
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="{$id}" /><input type="submit" class="delete" title="toggle delete" /></form></li> | ||
12 | </ul> | ||
11 | </div> | 13 | </div> |
12 | <header class="mbm"> | 14 | <header class="mbm"> |
13 | <h1><a href="{$url}">{$title}</a></h1> | 15 | <h1><a href="{$url}">{$title}</a></h1> |
@@ -24,6 +24,7 @@ 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']); | ||
27 | $tpl->draw('view'); | 28 | $tpl->draw('view'); |
28 | } | 29 | } |
29 | else { | 30 | else { |