aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc
diff options
context:
space:
mode:
Diffstat (limited to 'inc')
-rwxr-xr-x[-rw-r--r--]inc/3rdparty/libraries/feedwriter/FeedWriter.php168
-rwxr-xr-xinc/poche/Database.class.php96
-rwxr-xr-xinc/poche/Poche.class.php317
-rwxr-xr-xinc/poche/Tools.class.php8
-rwxr-xr-xinc/poche/config.inc.php.new14
5 files changed, 344 insertions, 259 deletions
diff --git a/inc/3rdparty/libraries/feedwriter/FeedWriter.php b/inc/3rdparty/libraries/feedwriter/FeedWriter.php
index adb2526c..5d16e765 100644..100755
--- a/inc/3rdparty/libraries/feedwriter/FeedWriter.php
+++ b/inc/3rdparty/libraries/feedwriter/FeedWriter.php
@@ -9,9 +9,9 @@ define('JSONP', 3, true);
9 * Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed) 9 * Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed)
10 * 10 *
11 * Modified for FiveFilters.org's Full-Text RSS project 11 * Modified for FiveFilters.org's Full-Text RSS project
12 * to allow for inclusion of hubs, JSON output. 12 * to allow for inclusion of hubs, JSON output.
13 * Stripped RSS1 and ATOM support. 13 * Stripped RSS1 and ATOM support.
14 * 14 *
15 * @package UnivarselFeedWriter 15 * @package UnivarselFeedWriter
16 * @author Anis uddin Ahmad <anisniit@gmail.com> 16 * @author Anis uddin Ahmad <anisniit@gmail.com>
17 * @link http://www.ajaxray.com/projects/rss 17 * @link http://www.ajaxray.com/projects/rss
@@ -26,32 +26,32 @@ define('JSONP', 3, true);
26 private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA 26 private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA
27 private $xsl = null; // stylesheet to render RSS (used by Chrome) 27 private $xsl = null; // stylesheet to render RSS (used by Chrome)
28 private $json = null; // JSON object 28 private $json = null; // JSON object
29 29
30 private $version = null; 30 private $version = null;
31 31
32 /** 32 /**
33 * Constructor 33 * Constructor
34 * 34 *
35 * @param constant the version constant (RSS2 or JSON). 35 * @param constant the version constant (RSS2 or JSON).
36 */ 36 */
37 function __construct($version = RSS2) 37 function __construct($version = RSS2)
38 { 38 {
39 $this->version = $version; 39 $this->version = $version;
40 40
41 // Setting default value for assential channel elements 41 // Setting default value for assential channel elements
42 $this->channels['title'] = $version . ' Feed'; 42 $this->channels['title'] = $version . ' Feed';
43 $this->channels['link'] = 'http://www.ajaxray.com/blog'; 43 $this->channels['link'] = 'http://www.ajaxray.com/blog';
44 44
45 //Tag names to encode in CDATA 45 //Tag names to encode in CDATA
46 $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary'); 46 $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');
47 } 47 }
48 48
49 public function setFormat($format) { 49 public function setFormat($format) {
50 $this->version = $format; 50 $this->version = $format;
51 } 51 }
52 52
53 // Start # public functions --------------------------------------------- 53 // Start # public functions ---------------------------------------------
54 54
55 /** 55 /**
56 * Set a channel element 56 * Set a channel element
57 * @access public 57 * @access public
@@ -63,11 +63,11 @@ define('JSONP', 3, true);
63 { 63 {
64 $this->channels[$elementName] = $content ; 64 $this->channels[$elementName] = $content ;
65 } 65 }
66 66
67 /** 67 /**
68 * Set multiple channel elements from an array. Array elements 68 * Set multiple channel elements from an array. Array elements
69 * should be 'channelName' => 'channelContent' format. 69 * should be 'channelName' => 'channelContent' format.
70 * 70 *
71 * @access public 71 * @access public
72 * @param array array of channels 72 * @param array array of channels
73 * @return void 73 * @return void
@@ -75,30 +75,30 @@ define('JSONP', 3, true);
75 public function setChannelElementsFromArray($elementArray) 75 public function setChannelElementsFromArray($elementArray)
76 { 76 {
77 if(! is_array($elementArray)) return; 77 if(! is_array($elementArray)) return;
78 foreach ($elementArray as $elementName => $content) 78 foreach ($elementArray as $elementName => $content)
79 { 79 {
80 $this->setChannelElement($elementName, $content); 80 $this->setChannelElement($elementName, $content);
81 } 81 }
82 } 82 }
83 83
84 /** 84 /**
85 * Genarate the actual RSS/JSON file 85 * Genarate the actual RSS/JSON file
86 * 86 *
87 * @access public 87 * @access public
88 * @return void 88 * @return void
89 */ 89 */
90 public function genarateFeed() 90 public function genarateFeed()
91 { 91 {
92 if ($this->version == RSS2) { 92 if ($this->version == RSS2) {
93 header('Content-type: text/xml; charset=UTF-8'); 93// header('Content-type: text/xml; charset=UTF-8');
94 // this line prevents Chrome 20 from prompting download 94 // this line prevents Chrome 20 from prompting download
95 // used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss 95 // used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss
96 header('X-content-type-options: nosniff'); 96// header('X-content-type-options: nosniff');
97 } elseif ($this->version == JSON) { 97 } elseif ($this->version == JSON) {
98 header('Content-type: application/json; charset=UTF-8'); 98// header('Content-type: application/json; charset=UTF-8');
99 $this->json = new stdClass(); 99 $this->json = new stdClass();
100 } elseif ($this->version == JSONP) { 100 } elseif ($this->version == JSONP) {
101 header('Content-type: application/javascript; charset=UTF-8'); 101// header('Content-type: application/javascript; charset=UTF-8');
102 $this->json = new stdClass(); 102 $this->json = new stdClass();
103 } 103 }
104 $this->printHead(); 104 $this->printHead();
@@ -109,10 +109,10 @@ define('JSONP', 3, true);
109 echo json_encode($this->json); 109 echo json_encode($this->json);
110 } 110 }
111 } 111 }
112 112
113 /** 113 /**
114 * Create a new FeedItem. 114 * Create a new FeedItem.
115 * 115 *
116 * @access public 116 * @access public
117 * @return object instance of FeedItem class 117 * @return object instance of FeedItem class
118 */ 118 */
@@ -121,24 +121,24 @@ define('JSONP', 3, true);
121 $Item = new FeedItem($this->version); 121 $Item = new FeedItem($this->version);
122 return $Item; 122 return $Item;
123 } 123 }
124 124
125 /** 125 /**
126 * Add a FeedItem to the main class 126 * Add a FeedItem to the main class
127 * 127 *
128 * @access public 128 * @access public
129 * @param object instance of FeedItem class 129 * @param object instance of FeedItem class
130 * @return void 130 * @return void
131 */ 131 */
132 public function addItem($feedItem) 132 public function addItem($feedItem)
133 { 133 {
134 $this->items[] = $feedItem; 134 $this->items[] = $feedItem;
135 } 135 }
136 136
137 // Wrapper functions ------------------------------------------------------------------- 137 // Wrapper functions -------------------------------------------------------------------
138 138
139 /** 139 /**
140 * Set the 'title' channel element 140 * Set the 'title' channel element
141 * 141 *
142 * @access public 142 * @access public
143 * @param srting value of 'title' channel tag 143 * @param srting value of 'title' channel tag
144 * @return void 144 * @return void
@@ -147,59 +147,59 @@ define('JSONP', 3, true);
147 { 147 {
148 $this->setChannelElement('title', $title); 148 $this->setChannelElement('title', $title);
149 } 149 }
150 150
151 /** 151 /**
152 * Add a hub to the channel element 152 * Add a hub to the channel element
153 * 153 *
154 * @access public 154 * @access public
155 * @param string URL 155 * @param string URL
156 * @return void 156 * @return void
157 */ 157 */
158 public function addHub($hub) 158 public function addHub($hub)
159 { 159 {
160 $this->hubs[] = $hub; 160 $this->hubs[] = $hub;
161 } 161 }
162 162
163 /** 163 /**
164 * Set XSL URL 164 * Set XSL URL
165 * 165 *
166 * @access public 166 * @access public
167 * @param string URL 167 * @param string URL
168 * @return void 168 * @return void
169 */ 169 */
170 public function setXsl($xsl) 170 public function setXsl($xsl)
171 { 171 {
172 $this->xsl = $xsl; 172 $this->xsl = $xsl;
173 } 173 }
174 174
175 /** 175 /**
176 * Set self URL 176 * Set self URL
177 * 177 *
178 * @access public 178 * @access public
179 * @param string URL 179 * @param string URL
180 * @return void 180 * @return void
181 */ 181 */
182 public function setSelf($self) 182 public function setSelf($self)
183 { 183 {
184 $this->self = $self; 184 $this->self = $self;
185 } 185 }
186 186
187 /** 187 /**
188 * Set the 'description' channel element 188 * Set the 'description' channel element
189 * 189 *
190 * @access public 190 * @access public
191 * @param srting value of 'description' channel tag 191 * @param srting value of 'description' channel tag
192 * @return void 192 * @return void
193 */ 193 */
194 public function setDescription($desciption) 194 public function setDescription($desciption)
195 { 195 {
196 $tag = ($this->version == ATOM)? 'subtitle' : 'description'; 196 $tag = ($this->version == ATOM)? 'subtitle' : 'description';
197 $this->setChannelElement($tag, $desciption); 197 $this->setChannelElement($tag, $desciption);
198 } 198 }
199 199
200 /** 200 /**
201 * Set the 'link' channel element 201 * Set the 'link' channel element
202 * 202 *
203 * @access public 203 * @access public
204 * @param srting value of 'link' channel tag 204 * @param srting value of 'link' channel tag
205 * @return void 205 * @return void
@@ -208,10 +208,10 @@ define('JSONP', 3, true);
208 { 208 {
209 $this->setChannelElement('link', $link); 209 $this->setChannelElement('link', $link);
210 } 210 }
211 211
212 /** 212 /**
213 * Set the 'image' channel element 213 * Set the 'image' channel element
214 * 214 *
215 * @access public 215 * @access public
216 * @param srting title of image 216 * @param srting title of image
217 * @param srting link url of the imahe 217 * @param srting link url of the imahe
@@ -222,14 +222,14 @@ define('JSONP', 3, true);
222 { 222 {
223 $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url)); 223 $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));
224 } 224 }
225 225
226 // End # public functions ---------------------------------------------- 226 // End # public functions ----------------------------------------------
227 227
228 // Start # private functions ---------------------------------------------- 228 // Start # private functions ----------------------------------------------
229 229
230 /** 230 /**
231 * Prints the xml and rss namespace 231 * Prints the xml and rss namespace
232 * 232 *
233 * @access private 233 * @access private
234 * @return void 234 * @return void
235 */ 235 */
@@ -247,10 +247,10 @@ define('JSONP', 3, true);
247 $this->json->rss = array('@attributes' => array('version' => '2.0')); 247 $this->json->rss = array('@attributes' => array('version' => '2.0'));
248 } 248 }
249 } 249 }
250 250
251 /** 251 /**
252 * Closes the open tags at the end of file 252 * Closes the open tags at the end of file
253 * 253 *
254 * @access private 254 * @access private
255 * @return void 255 * @return void
256 */ 256 */
@@ -258,14 +258,14 @@ define('JSONP', 3, true);
258 { 258 {
259 if ($this->version == RSS2) 259 if ($this->version == RSS2)
260 { 260 {
261 echo '</channel>',PHP_EOL,'</rss>'; 261 echo '</channel>',PHP_EOL,'</rss>';
262 } 262 }
263 // do nothing for JSON 263 // do nothing for JSON
264 } 264 }
265 265
266 /** 266 /**
267 * Creates a single node as xml format 267 * Creates a single node as xml format
268 * 268 *
269 * @access private 269 * @access private
270 * @param string name of the tag 270 * @param string name of the tag
271 * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format 271 * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format
@@ -273,22 +273,22 @@ define('JSONP', 3, true);
273 * @return string formatted xml tag 273 * @return string formatted xml tag
274 */ 274 */
275 private function makeNode($tagName, $tagContent, $attributes = null) 275 private function makeNode($tagName, $tagContent, $attributes = null)
276 { 276 {
277 if ($this->version == RSS2) 277 if ($this->version == RSS2)
278 { 278 {
279 $nodeText = ''; 279 $nodeText = '';
280 $attrText = ''; 280 $attrText = '';
281 if (is_array($attributes)) 281 if (is_array($attributes))
282 { 282 {
283 foreach ($attributes as $key => $value) 283 foreach ($attributes as $key => $value)
284 { 284 {
285 $attrText .= " $key=\"$value\" "; 285 $attrText .= " $key=\"$value\" ";
286 } 286 }
287 } 287 }
288 $nodeText .= "<{$tagName}{$attrText}>"; 288 $nodeText .= "<{$tagName}{$attrText}>";
289 if (is_array($tagContent)) 289 if (is_array($tagContent))
290 { 290 {
291 foreach ($tagContent as $key => $value) 291 foreach ($tagContent as $key => $value)
292 { 292 {
293 $nodeText .= $this->makeNode($key, $value); 293 $nodeText .= $this->makeNode($key, $value);
294 } 294 }
@@ -297,7 +297,7 @@ define('JSONP', 3, true);
297 { 297 {
298 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent); 298 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
299 $nodeText .= htmlspecialchars($tagContent); 299 $nodeText .= htmlspecialchars($tagContent);
300 } 300 }
301 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>"; 301 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
302 $nodeText .= "</$tagName>"; 302 $nodeText .= "</$tagName>";
303 return $nodeText . PHP_EOL; 303 return $nodeText . PHP_EOL;
@@ -321,7 +321,7 @@ define('JSONP', 3, true);
321 } 321 }
322 return ''; // should not get here 322 return ''; // should not get here
323 } 323 }
324 324
325 private function json_keys(array $array) { 325 private function json_keys(array $array) {
326 $new = array(); 326 $new = array();
327 foreach ($array as $key => $val) { 327 foreach ($array as $key => $val) {
@@ -334,7 +334,7 @@ define('JSONP', 3, true);
334 } 334 }
335 return $new; 335 return $new;
336 } 336 }
337 337
338 /** 338 /**
339 * @desc Print channels 339 * @desc Print channels
340 * @access private 340 * @access private
@@ -344,7 +344,7 @@ define('JSONP', 3, true);
344 { 344 {
345 //Start channel tag 345 //Start channel tag
346 if ($this->version == RSS2) { 346 if ($this->version == RSS2) {
347 echo '<channel>' . PHP_EOL; 347 echo '<channel>' . PHP_EOL;
348 // add hubs 348 // add hubs
349 foreach ($this->hubs as $hub) { 349 foreach ($this->hubs as $hub) {
350 //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom')); 350 //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));
@@ -356,7 +356,7 @@ define('JSONP', 3, true);
356 echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL; 356 echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
357 } 357 }
358 //Print Items of channel 358 //Print Items of channel
359 foreach ($this->channels as $key => $value) 359 foreach ($this->channels as $key => $value)
360 { 360 {
361 echo $this->makeNode($key, $value); 361 echo $this->makeNode($key, $value);
362 } 362 }
@@ -364,26 +364,26 @@ define('JSONP', 3, true);
364 $this->json->rss['channel'] = (object)$this->json_keys($this->channels); 364 $this->json->rss['channel'] = (object)$this->json_keys($this->channels);
365 } 365 }
366 } 366 }
367 367
368 /** 368 /**
369 * Prints formatted feed items 369 * Prints formatted feed items
370 * 370 *
371 * @access private 371 * @access private
372 * @return void 372 * @return void
373 */ 373 */
374 private function printItems() 374 private function printItems()
375 { 375 {
376 foreach ($this->items as $item) { 376 foreach ($this->items as $item) {
377 $itemElements = $item->getElements(); 377 $itemElements = $item->getElements();
378 378
379 echo $this->startItem(); 379 echo $this->startItem();
380 380
381 if ($this->version == JSON || $this->version == JSONP) { 381 if ($this->version == JSON || $this->version == JSONP) {
382 $json_item = array(); 382 $json_item = array();
383 } 383 }
384 384
385 foreach ($itemElements as $thisElement) { 385 foreach ($itemElements as $thisElement) {
386 foreach ($thisElement as $instance) { 386 foreach ($thisElement as $instance) {
387 if ($this->version == RSS2) { 387 if ($this->version == RSS2) {
388 echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']); 388 echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);
389 } elseif ($this->version == JSON || $this->version == JSONP) { 389 } elseif ($this->version == JSON || $this->version == JSONP) {
@@ -406,10 +406,10 @@ define('JSONP', 3, true);
406 } 406 }
407 } 407 }
408 } 408 }
409 409
410 /** 410 /**
411 * Make the starting tag of channels 411 * Make the starting tag of channels
412 * 412 *
413 * @access private 413 * @access private
414 * @return void 414 * @return void
415 */ 415 */
@@ -417,14 +417,14 @@ define('JSONP', 3, true);
417 { 417 {
418 if ($this->version == RSS2) 418 if ($this->version == RSS2)
419 { 419 {
420 echo '<item>' . PHP_EOL; 420 echo '<item>' . PHP_EOL;
421 } 421 }
422 // nothing for JSON 422 // nothing for JSON
423 } 423 }
424 424
425 /** 425 /**
426 * Closes feed item tag 426 * Closes feed item tag
427 * 427 *
428 * @access private 428 * @access private
429 * @return void 429 * @return void
430 */ 430 */
@@ -432,10 +432,10 @@ define('JSONP', 3, true);
432 { 432 {
433 if ($this->version == RSS2) 433 if ($this->version == RSS2)
434 { 434 {
435 echo '</item>' . PHP_EOL; 435 echo '</item>' . PHP_EOL;
436 } 436 }
437 // nothing for JSON 437 // nothing for JSON
438 } 438 }
439 439
440 // End # private functions ---------------------------------------------- 440 // End # private functions ----------------------------------------------
441 } \ No newline at end of file 441 } \ No newline at end of file
diff --git a/inc/poche/Database.class.php b/inc/poche/Database.class.php
index 2257f281..6244df88 100755
--- a/inc/poche/Database.class.php
+++ b/inc/poche/Database.class.php
@@ -18,7 +18,7 @@ class Database {
18 'default' => 'ORDER BY entries.id' 18 'default' => 'ORDER BY entries.id'
19 ); 19 );
20 20
21 function __construct() 21 function __construct()
22 { 22 {
23 switch (STORAGE) { 23 switch (STORAGE) {
24 case 'sqlite': 24 case 'sqlite':
@@ -27,11 +27,11 @@ class Database {
27 break; 27 break;
28 case 'mysql': 28 case 'mysql':
29 $db_path = 'mysql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB; 29 $db_path = 'mysql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
30 $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD); 30 $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
31 break; 31 break;
32 case 'postgres': 32 case 'postgres':
33 $db_path = 'pgsql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB; 33 $db_path = 'pgsql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
34 $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD); 34 $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
35 break; 35 break;
36 } 36 }
37 37
@@ -51,7 +51,7 @@ class Database {
51 } 51 }
52 $hasAdmin = count($query->fetchAll()); 52 $hasAdmin = count($query->fetchAll());
53 53
54 if ($hasAdmin == 0) 54 if ($hasAdmin == 0)
55 return false; 55 return false;
56 56
57 return true; 57 return true;
@@ -140,7 +140,7 @@ class Database {
140 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)'; 140 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
141 $params = array($id_user, 'language', LANG); 141 $params = array($id_user, 'language', LANG);
142 $query = $this->executeQuery($sql, $params); 142 $query = $this->executeQuery($sql, $params);
143 143
144 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)'; 144 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
145 $params = array($id_user, 'theme', DEFAULT_THEME); 145 $params = array($id_user, 'theme', DEFAULT_THEME);
146 $query = $this->executeQuery($sql, $params); 146 $query = $this->executeQuery($sql, $params);
@@ -153,7 +153,7 @@ class Database {
153 $query = $this->executeQuery($sql, array($id)); 153 $query = $this->executeQuery($sql, array($id));
154 $result = $query->fetchAll(); 154 $result = $query->fetchAll();
155 $user_config = array(); 155 $user_config = array();
156 156
157 foreach ($result as $key => $value) { 157 foreach ($result as $key => $value) {
158 $user_config[$value['name']] = $value['value']; 158 $user_config[$value['name']] = $value['value'];
159 } 159 }
@@ -201,10 +201,10 @@ class Database {
201 $params_update = array($password, $userId); 201 $params_update = array($password, $userId);
202 $query = $this->executeQuery($sql_update, $params_update); 202 $query = $this->executeQuery($sql_update, $params_update);
203 } 203 }
204 204
205 public function updateUserConfig($userId, $key, $value) { 205 public function updateUserConfig($userId, $key, $value) {
206 $config = $this->getConfigUser($userId); 206 $config = $this->getConfigUser($userId);
207 207
208 if (! isset($config[$key])) { 208 if (! isset($config[$key])) {
209 $sql = "INSERT INTO users_config (value, user_id, name) VALUES (?, ?, ?)"; 209 $sql = "INSERT INTO users_config (value, user_id, name) VALUES (?, ?, ?)";
210 } 210 }
@@ -252,8 +252,16 @@ class Database {
252 return $entries; 252 return $entries;
253 } 253 }
254 254
255 public function retrieveUnfetchedEntriesCount($user_id) {
256 $sql = "SELECT count(*) FROM entries WHERE (content = '' OR content IS NULL) AND user_id=?";
257 $query = $this->executeQuery($sql, array($user_id));
258 list($count) = $query->fetch();
259
260 return $count;
261 }
262
255 public function retrieveAll($user_id) { 263 public function retrieveAll($user_id) {
256 $sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? ORDER BY id"; 264 $sql = "SELECT * FROM entries WHERE user_id=? ORDER BY id";
257 $query = $this->executeQuery($sql, array($user_id)); 265 $query = $this->executeQuery($sql, array($user_id));
258 $entries = $query->fetchAll(); 266 $entries = $query->fetchAll();
259 267
@@ -272,7 +280,7 @@ class Database {
272 280
273 public function retrieveOneByURL($url, $user_id) { 281 public function retrieveOneByURL($url, $user_id) {
274 $entry = NULL; 282 $entry = NULL;
275 $sql = "SELECT * FROM entries WHERE content <> '' AND url=? AND user_id=?"; 283 $sql = "SELECT * FROM entries WHERE url=? AND user_id=?";
276 $params = array($url, $user_id); 284 $params = array($url, $user_id);
277 $query = $this->executeQuery($sql, $params); 285 $query = $this->executeQuery($sql, $params);
278 $entry = $query->fetchAll(); 286 $entry = $query->fetchAll();
@@ -289,22 +297,21 @@ class Database {
289 public function getEntriesByView($view, $user_id, $limit = '', $tag_id = 0) { 297 public function getEntriesByView($view, $user_id, $limit = '', $tag_id = 0) {
290 switch ($view) { 298 switch ($view) {
291 case 'archive': 299 case 'archive':
292 $sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; 300 $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? ";
293 $params = array($user_id, 1); 301 $params = array($user_id, 1);
294 break; 302 break;
295 case 'fav' : 303 case 'fav' :
296 $sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? AND is_fav=? "; 304 $sql = "SELECT * FROM entries WHERE user_id=? AND is_fav=? ";
297 $params = array($user_id, 1); 305 $params = array($user_id, 1);
298 break; 306 break;
299 case 'tag' : 307 case 'tag' :
300 $sql = "SELECT entries.* FROM entries 308 $sql = "SELECT entries.* FROM entries
301 LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id 309 LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
302 WHERE entries.content <> '' AND 310 WHERE entries.user_id=? AND tags_entries.tag_id = ? ";
303 entries.user_id=? AND tags_entries.tag_id = ? ";
304 $params = array($user_id, $tag_id); 311 $params = array($user_id, $tag_id);
305 break; 312 break;
306 default: 313 default:
307 $sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; 314 $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? ";
308 $params = array($user_id, 0); 315 $params = array($user_id, 0);
309 break; 316 break;
310 } 317 }
@@ -320,22 +327,21 @@ class Database {
320 public function getEntriesByViewCount($view, $user_id, $tag_id = 0) { 327 public function getEntriesByViewCount($view, $user_id, $tag_id = 0) {
321 switch ($view) { 328 switch ($view) {
322 case 'archive': 329 case 'archive':
323 $sql = "SELECT count(*) FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; 330 $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
324 $params = array($user_id, 1); 331 $params = array($user_id, 1);
325 break; 332 break;
326 case 'fav' : 333 case 'fav' :
327 $sql = "SELECT count(*) FROM entries WHERE content <> '' AND user_id=? AND is_fav=? "; 334 $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_fav=? ";
328 $params = array($user_id, 1); 335 $params = array($user_id, 1);
329 break; 336 break;
330 case 'tag' : 337 case 'tag' :
331 $sql = "SELECT count(*) FROM entries 338 $sql = "SELECT count(*) FROM entries
332 LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id 339 LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
333 WHERE entries.content <> '' AND 340 WHERE entries.user_id=? AND tags_entries.tag_id = ? ";
334 entries.user_id=? AND tags_entries.tag_id = ? ";
335 $params = array($user_id, $tag_id); 341 $params = array($user_id, $tag_id);
336 break; 342 break;
337 default: 343 default:
338 $sql = "SELECT count(*) FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; 344 $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
339 $params = array($user_id, 0); 345 $params = array($user_id, 0);
340 break; 346 break;
341 } 347 }
@@ -353,11 +359,24 @@ class Database {
353 return $query; 359 return $query;
354 } 360 }
355 361
356 public function add($url, $title, $content, $user_id) { 362 /**
357 $sql_action = 'INSERT INTO entries ( url, title, content, user_id ) VALUES (?, ?, ?, ?)'; 363 *
358 $params_action = array($url, $title, $content, $user_id); 364 * @param string $url
359 $query = $this->executeQuery($sql_action, $params_action); 365 * @param string $title
360 return $query; 366 * @param string $content
367 * @param integer $user_id
368 * @return integer $id of inserted record
369 */
370 public function add($url, $title, $content, $user_id, $isFavorite=0, $isRead=0) {
371 $sql_action = 'INSERT INTO entries ( url, title, content, user_id, is_fav, is_read ) VALUES (?, ?, ?, ?, ?, ?)';
372 $params_action = array($url, $title, $content, $user_id, $isFavorite, $isRead);
373 if ( !$this->executeQuery($sql_action, $params_action) ) {
374 $id = null;
375 }
376 else {
377 $id = intval($this->getLastId( (STORAGE == 'postgres') ? 'users_id_seq' : '' ));
378 }
379 return $id;
361 } 380 }
362 381
363 public function deleteById($id, $user_id) { 382 public function deleteById($id, $user_id) {
@@ -389,20 +408,20 @@ class Database {
389 return $this->getHandle()->lastInsertId($column); 408 return $this->getHandle()->lastInsertId($column);
390 } 409 }
391 410
392 public function search($term,$id,$limit = ''){ 411 public function search($term, $user_id, $limit = '') {
393 $search = '%'.$term.'%'; 412 $search = '%'.$term.'%';
394 $sql_action = ("SELECT * FROM entries WHERE user_id=? AND (content LIKE ? OR title LIKE ? OR url LIKE ?) "); //searches in content, title and URL 413 $sql_action = "SELECT * FROM entries WHERE user_id=? AND (content LIKE ? OR title LIKE ? OR url LIKE ?) "; //searches in content, title and URL
395 $sql_action .= $this->getEntriesOrder().' ' . $limit; 414 $sql_action .= $this->getEntriesOrder().' ' . $limit;
396 $params_action = array($id,$search,$search,$search); 415 $params_action = array($user_id, $search, $search, $search);
397 $query = $this->executeQuery($sql_action, $params_action); 416 $query = $this->executeQuery($sql_action, $params_action);
398 return $query->fetchAll(); 417 return $query->fetchAll();
399 } 418 }
400 419
401 public function retrieveAllTags($user_id, $term = null) { 420 public function retrieveAllTags($user_id, $term = null) {
402 $sql = "SELECT DISTINCT tags.*, count(entries.id) AS entriescount FROM tags 421 $sql = "SELECT DISTINCT tags.*, count(entries.id) AS entriescount FROM tags
403 LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id 422 LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
404 LEFT JOIN entries ON tags_entries.entry_id=entries.id 423 LEFT JOIN entries ON tags_entries.entry_id=entries.id
405 WHERE entries.content <> '' AND entries.user_id=? 424 WHERE entries.user_id=?
406 ". (($term) ? "AND lower(tags.value) LIKE ?" : '') ." 425 ". (($term) ? "AND lower(tags.value) LIKE ?" : '') ."
407 GROUP BY tags.id, tags.value 426 GROUP BY tags.id, tags.value
408 ORDER BY tags.value"; 427 ORDER BY tags.value";
@@ -417,7 +436,7 @@ class Database {
417 $sql = "SELECT DISTINCT tags.* FROM tags 436 $sql = "SELECT DISTINCT tags.* FROM tags
418 LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id 437 LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
419 LEFT JOIN entries ON tags_entries.entry_id=entries.id 438 LEFT JOIN entries ON tags_entries.entry_id=entries.id
420 WHERE entries.content <> '' AND tags.id=? AND entries.user_id=?"; 439 WHERE tags.id=? AND entries.user_id=?";
421 $params = array(intval($id), $user_id); 440 $params = array(intval($id), $user_id);
422 $query = $this->executeQuery($sql, $params); 441 $query = $this->executeQuery($sql, $params);
423 $tag = $query->fetchAll(); 442 $tag = $query->fetchAll();
@@ -426,11 +445,10 @@ class Database {
426 } 445 }
427 446
428 public function retrieveEntriesByTag($tag_id, $user_id) { 447 public function retrieveEntriesByTag($tag_id, $user_id) {
429 $sql = 448 $sql =
430 "SELECT entries.* FROM entries 449 "SELECT entries.* FROM entries
431 LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id 450 LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
432 WHERE entries.content <> '' AND 451 WHERE tags_entries.tag_id = ? AND entries.user_id=?";
433 tags_entries.tag_id = ? AND entries.user_id=?";
434 $query = $this->executeQuery($sql, array($tag_id, $user_id)); 452 $query = $this->executeQuery($sql, array($tag_id, $user_id));
435 $entries = $query->fetchAll(); 453 $entries = $query->fetchAll();
436 454
@@ -438,7 +456,7 @@ class Database {
438 } 456 }
439 457
440 public function retrieveTagsByEntry($entry_id) { 458 public function retrieveTagsByEntry($entry_id) {
441 $sql = 459 $sql =
442 "SELECT tags.* FROM tags 460 "SELECT tags.* FROM tags
443 LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id 461 LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
444 WHERE tags_entries.entry_id = ?"; 462 WHERE tags_entries.entry_id = ?";
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php
index 42a2dd9a..ee3b2ac2 100755
--- a/inc/poche/Poche.class.php
+++ b/inc/poche/Poche.class.php
@@ -18,7 +18,7 @@ class Poche
18 public $tpl; 18 public $tpl;
19 public $messages; 19 public $messages;
20 public $pagination; 20 public $pagination;
21 21
22 private $currentTheme = ''; 22 private $currentTheme = '';
23 private $currentLanguage = ''; 23 private $currentLanguage = '';
24 private $notInstalledMessage = array(); 24 private $notInstalledMessage = array();
@@ -42,11 +42,11 @@ class Poche
42 if ($this->configFileIsAvailable()) { 42 if ($this->configFileIsAvailable()) {
43 $this->init(); 43 $this->init();
44 } 44 }
45 45
46 if ($this->themeIsInstalled()) { 46 if ($this->themeIsInstalled()) {
47 $this->initTpl(); 47 $this->initTpl();
48 } 48 }
49 49
50 if ($this->systemIsInstalled()) { 50 if ($this->systemIsInstalled()) {
51 $this->store = new Database(); 51 $this->store = new Database();
52 $this->messages = new Messages(); 52 $this->messages = new Messages();
@@ -57,8 +57,8 @@ class Poche
57 $this->store->checkTags(); 57 $this->store->checkTags();
58 } 58 }
59 } 59 }
60 60
61 private function init() 61 private function init()
62 { 62 {
63 Tools::initPhp(); 63 Tools::initPhp();
64 64
@@ -74,28 +74,28 @@ class Poche
74 $language = $this->user->getConfigValue('language'); 74 $language = $this->user->getConfigValue('language');
75 putenv('LC_ALL=' . $language); 75 putenv('LC_ALL=' . $language);
76 setlocale(LC_ALL, $language); 76 setlocale(LC_ALL, $language);
77 bindtextdomain($language, LOCALE); 77 bindtextdomain($language, LOCALE);
78 textdomain($language); 78 textdomain($language);
79 79
80 # Pagination 80 # Pagination
81 $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p'); 81 $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p');
82 82
83 # Set up theme 83 # Set up theme
84 $themeDirectory = $this->user->getConfigValue('theme'); 84 $themeDirectory = $this->user->getConfigValue('theme');
85 85
86 if ($themeDirectory === false) { 86 if ($themeDirectory === false) {
87 $themeDirectory = DEFAULT_THEME; 87 $themeDirectory = DEFAULT_THEME;
88 } 88 }
89 89
90 $this->currentTheme = $themeDirectory; 90 $this->currentTheme = $themeDirectory;
91 91
92 # Set up language 92 # Set up language
93 $languageDirectory = $this->user->getConfigValue('language'); 93 $languageDirectory = $this->user->getConfigValue('language');
94 94
95 if ($languageDirectory === false) { 95 if ($languageDirectory === false) {
96 $languageDirectory = DEFAULT_THEME; 96 $languageDirectory = DEFAULT_THEME;
97 } 97 }
98 98
99 $this->currentLanguage = $languageDirectory; 99 $this->currentLanguage = $languageDirectory;
100 } 100 }
101 101
@@ -108,7 +108,7 @@ class Poche
108 108
109 return true; 109 return true;
110 } 110 }
111 111
112 public function themeIsInstalled() { 112 public function themeIsInstalled() {
113 $passTheme = TRUE; 113 $passTheme = TRUE;
114 # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet 114 # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet
@@ -123,27 +123,27 @@ class Poche
123 self::$canRenderTemplates = false; 123 self::$canRenderTemplates = false;
124 124
125 $passTheme = FALSE; 125 $passTheme = FALSE;
126 } 126 }
127 127
128 # Check if the selected theme and its requirements are present 128 # Check if the selected theme and its requirements are present
129 $theme = $this->getTheme(); 129 $theme = $this->getTheme();
130 130
131 if ($theme != '' && ! is_dir(THEME . '/' . $theme)) { 131 if ($theme != '' && ! is_dir(THEME . '/' . $theme)) {
132 $this->notInstalledMessage[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $theme . ')'; 132 $this->notInstalledMessage[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $theme . ')';
133 133
134 self::$canRenderTemplates = false; 134 self::$canRenderTemplates = false;
135 135
136 $passTheme = FALSE; 136 $passTheme = FALSE;
137 } 137 }
138 138
139 $themeInfo = $this->getThemeInfo($theme); 139 $themeInfo = $this->getThemeInfo($theme);
140 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) { 140 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) {
141 foreach ($themeInfo['requirements'] as $requiredTheme) { 141 foreach ($themeInfo['requirements'] as $requiredTheme) {
142 if (! is_dir(THEME . '/' . $requiredTheme)) { 142 if (! is_dir(THEME . '/' . $requiredTheme)) {
143 $this->notInstalledMessage[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')'; 143 $this->notInstalledMessage[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')';
144 144
145 self::$canRenderTemplates = false; 145 self::$canRenderTemplates = false;
146 146
147 $passTheme = FALSE; 147 $passTheme = FALSE;
148 } 148 }
149 } 149 }
@@ -153,21 +153,21 @@ class Poche
153 return FALSE; 153 return FALSE;
154 } 154 }
155 155
156 156
157 return true; 157 return true;
158 } 158 }
159 159
160 /** 160 /**
161 * all checks before installation. 161 * all checks before installation.
162 * @todo move HTML to template 162 * @todo move HTML to template
163 * @return boolean 163 * @return boolean
164 */ 164 */
165 public function systemIsInstalled() 165 public function systemIsInstalled()
166 { 166 {
167 $msg = TRUE; 167 $msg = TRUE;
168 168
169 $configSalt = defined('SALT') ? constant('SALT') : ''; 169 $configSalt = defined('SALT') ? constant('SALT') : '';
170 170
171 if (empty($configSalt)) { 171 if (empty($configSalt)) {
172 $this->notInstalledMessage[] = 'You have not yet filled in the SALT value in the config.inc.php file.'; 172 $this->notInstalledMessage[] = 'You have not yet filled in the SALT value in the config.inc.php file.';
173 $msg = FALSE; 173 $msg = FALSE;
@@ -193,7 +193,7 @@ class Poche
193 193
194 return true; 194 return true;
195 } 195 }
196 196
197 public function getNotInstalledMessage() { 197 public function getNotInstalledMessage() {
198 return $this->notInstalledMessage; 198 return $this->notInstalledMessage;
199 } 199 }
@@ -202,7 +202,7 @@ class Poche
202 { 202 {
203 $loaderChain = new Twig_Loader_Chain(); 203 $loaderChain = new Twig_Loader_Chain();
204 $theme = $this->getTheme(); 204 $theme = $this->getTheme();
205 205
206 # add the current theme as first to the loader chain so Twig will look there first for overridden template files 206 # add the current theme as first to the loader chain so Twig will look there first for overridden template files
207 try { 207 try {
208 $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $theme)); 208 $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $theme));
@@ -210,7 +210,7 @@ class Poche
210 # @todo isInstalled() should catch this, inject Twig later 210 # @todo isInstalled() should catch this, inject Twig later
211 die('The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME . '/' . $theme .' is missing)'); 211 die('The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME . '/' . $theme .' is missing)');
212 } 212 }
213 213
214 # add all required themes to the loader chain 214 # add all required themes to the loader chain
215 $themeInfo = $this->getThemeInfo($theme); 215 $themeInfo = $this->getThemeInfo($theme);
216 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) { 216 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) {
@@ -223,16 +223,16 @@ class Poche
223 } 223 }
224 } 224 }
225 } 225 }
226 226
227 if (DEBUG_POCHE) { 227 if (DEBUG_POCHE) {
228 $twigParams = array(); 228 $twigParams = array();
229 } else { 229 } else {
230 $twigParams = array('cache' => CACHE); 230 $twigParams = array('cache' => CACHE);
231 } 231 }
232 232
233 $this->tpl = new Twig_Environment($loaderChain, $twigParams); 233 $this->tpl = new Twig_Environment($loaderChain, $twigParams);
234 $this->tpl->addExtension(new Twig_Extensions_Extension_I18n()); 234 $this->tpl->addExtension(new Twig_Extensions_Extension_I18n());
235 235
236 # filter to display domain name of an url 236 # filter to display domain name of an url
237 $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain'); 237 $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain');
238 $this->tpl->addFilter($filter); 238 $this->tpl->addFilter($filter);
@@ -251,7 +251,7 @@ class Poche
251 'poche_url' => Tools::getPocheUrl() 251 'poche_url' => Tools::getPocheUrl()
252 )); 252 ));
253 if (isset($_GET['install'])) { 253 if (isset($_GET['install'])) {
254 if (($_POST['password'] == $_POST['password_repeat']) 254 if (($_POST['password'] == $_POST['password_repeat'])
255 && $_POST['password'] != "" && $_POST['login'] != "") { 255 && $_POST['password'] != "" && $_POST['login'] != "") {
256 # let's rock, install poche baby ! 256 # let's rock, install poche baby !
257 if ($this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']))) 257 if ($this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login'])))
@@ -268,7 +268,7 @@ class Poche
268 } 268 }
269 exit(); 269 exit();
270 } 270 }
271 271
272 public function getTheme() { 272 public function getTheme() {
273 return $this->currentTheme; 273 return $this->currentTheme;
274 } 274 }
@@ -293,7 +293,7 @@ class Poche
293 if (is_file($themeIniFile) && is_readable($themeIniFile)) { 293 if (is_file($themeIniFile) && is_readable($themeIniFile)) {
294 $themeInfo = parse_ini_file($themeIniFile); 294 $themeInfo = parse_ini_file($themeIniFile);
295 } 295 }
296 296
297 if ($themeInfo === false) { 297 if ($themeInfo === false) {
298 $themeInfo = array(); 298 $themeInfo = array();
299 } 299 }
@@ -304,7 +304,7 @@ class Poche
304 304
305 return $themeInfo; 305 return $themeInfo;
306 } 306 }
307 307
308 public function getInstalledThemes() { 308 public function getInstalledThemes() {
309 $handle = opendir(THEME); 309 $handle = opendir(THEME);
310 $themes = array(); 310 $themes = array();
@@ -331,28 +331,28 @@ class Poche
331 public function getInstalledLanguages() { 331 public function getInstalledLanguages() {
332 $handle = opendir(LOCALE); 332 $handle = opendir(LOCALE);
333 $languages = array(); 333 $languages = array();
334 334
335 while (($language = readdir($handle)) !== false) { 335 while (($language = readdir($handle)) !== false) {
336 # Languages are stored in a directory, so all directory names are languages 336 # Languages are stored in a directory, so all directory names are languages
337 # @todo move language installation data to database 337 # @todo move language installation data to database
338 if (! is_dir(LOCALE . '/' . $language) || in_array($language, array('..', '.', 'tools'))) { 338 if (! is_dir(LOCALE . '/' . $language) || in_array($language, array('..', '.', 'tools'))) {
339 continue; 339 continue;
340 } 340 }
341 341
342 $current = false; 342 $current = false;
343 343
344 if ($language === $this->getLanguage()) { 344 if ($language === $this->getLanguage()) {
345 $current = true; 345 $current = true;
346 } 346 }
347 347
348 $languages[] = array('name' => (isset($this->language_names[$language]) ? $this->language_names[$language] : $language), 'value' => $language, 'current' => $current); 348 $languages[] = array('name' => (isset($this->language_names[$language]) ? $this->language_names[$language] : $language), 'value' => $language, 'current' => $current);
349 } 349 }
350 350
351 return $languages; 351 return $languages;
352 } 352 }
353 353
354 public function getDefaultConfig() 354 public function getDefaultConfig()
355 { 355 {
356 return array( 356 return array(
357 'pager' => PAGINATION, 357 'pager' => PAGINATION,
358 'language' => LANG, 358 'language' => LANG,
@@ -385,19 +385,15 @@ class Poche
385 $body = ''; 385 $body = '';
386 } 386 }
387 387
388 //search for possible duplicate if not in import mode 388 //search for possible duplicate
389 $duplicate = NULL; 389 $duplicate = NULL;
390 if (!$import) { 390 if (!$import) {
391 $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId()); 391 $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId());
392 } 392 }
393 393
394 if ($this->store->add($url->getUrl(), $title, $body, $this->user->getId())) { 394 $last_id = $this->store->add($url->getUrl(), $title, $body, $this->user->getId());
395 if ( $last_id && !$import ) {
395 Tools::logm('add link ' . $url->getUrl()); 396 Tools::logm('add link ' . $url->getUrl());
396 $sequence = '';
397 if (STORAGE == 'postgres') {
398 $sequence = 'entries_id_seq';
399 }
400 $last_id = $this->store->getLastId($sequence);
401 if (DOWNLOAD_PICTURES) { 397 if (DOWNLOAD_PICTURES) {
402 $content = filtre_picture($body, $url->getUrl(), $last_id); 398 $content = filtre_picture($body, $url->getUrl(), $last_id);
403 Tools::logm('updating content article'); 399 Tools::logm('updating content article');
@@ -417,9 +413,7 @@ class Poche
417 } 413 }
418 } 414 }
419 415
420 if (!$import) { 416 $this->messages->add('s', _('the link has been added successfully'));
421 $this->messages->add('s', _('the link has been added successfully'));
422 }
423 } 417 }
424 else { 418 else {
425 if (!$import) { 419 if (!$import) {
@@ -603,20 +597,19 @@ class Poche
603 'tags' => $tags, 597 'tags' => $tags,
604 ); 598 );
605 break; 599 break;
606 600 case 'search':
607 case 'search': 601 if (isset($_GET['search'])) {
608 if (isset($_GET['search'])){ 602 $search = filter_var($_GET['search'], FILTER_SANITIZE_STRING);
609 $search = filter_var($_GET['search'], FILTER_SANITIZE_STRING); 603 $tpl_vars['entries'] = $this->store->search($search, $this->user->getId());
610 $tpl_vars['entries'] = $this->store->search($search,$this->user->getId()); 604 $count = count($tpl_vars['entries']);
611 $count = count($tpl_vars['entries']); 605 $this->pagination->set_total($count);
612 $this->pagination->set_total($count); 606 $page_links = str_replace(array('previous', 'next'), array(_('previous'), _('next')),
613 $page_links = str_replace(array('previous', 'next'), array(_('previous'), _('next')), 607 $this->pagination->page_links('?view=' . $view . '?search=' . $search . '&sort=' . $_SESSION['sort'] . '&' ));
614 $this->pagination->page_links('?view=' . $view . '?search=' . $search . '&sort=' . $_SESSION['sort'] . '&' )); 608 $tpl_vars['page_links'] = $page_links;
615 $tpl_vars['page_links'] = $page_links; 609 $tpl_vars['nb_results'] = $count;
616 $tpl_vars['nb_results'] = $count; 610 $tpl_vars['search_term'] = $search;
617 $tpl_vars['search_term'] = $search; 611 }
618 } 612 break;
619 break;
620 case 'view': 613 case 'view':
621 $entry = $this->store->retrieveOneById($id, $this->user->getId()); 614 $entry = $this->store->retrieveOneById($id, $this->user->getId());
622 if ($entry != NULL) { 615 if ($entry != NULL) {
@@ -653,7 +646,7 @@ class Poche
653 'nb_results' => '', 646 'nb_results' => '',
654 'listmode' => (isset($_COOKIE['listmode']) ? true : false), 647 'listmode' => (isset($_COOKIE['listmode']) ? true : false),
655 ); 648 );
656 649
657 //if id is given - we retrive entries by tag: id is tag id 650 //if id is given - we retrive entries by tag: id is tag id
658 if ($id) { 651 if ($id) {
659 $tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId()); 652 $tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId());
@@ -678,8 +671,8 @@ class Poche
678 } 671 }
679 672
680 /** 673 /**
681 * update the password of the current user. 674 * update the password of the current user.
682 * if MODE_DEMO is TRUE, the password can't be updated. 675 * if MODE_DEMO is TRUE, the password can't be updated.
683 * @todo add the return value 676 * @todo add the return value
684 * @todo set the new password in function header like this updatePassword($newPassword) 677 * @todo set the new password in function header like this updatePassword($newPassword)
685 * @return boolean 678 * @return boolean
@@ -707,44 +700,44 @@ class Poche
707 } 700 }
708 } 701 }
709 } 702 }
710 703
711 public function updateTheme() 704 public function updateTheme()
712 { 705 {
713 # no data 706 # no data
714 if (empty($_POST['theme'])) { 707 if (empty($_POST['theme'])) {
715 } 708 }
716 709
717 # we are not going to change it to the current theme... 710 # we are not going to change it to the current theme...
718 if ($_POST['theme'] == $this->getTheme()) { 711 if ($_POST['theme'] == $this->getTheme()) {
719 $this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!')); 712 $this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!'));
720 Tools::redirect('?view=config'); 713 Tools::redirect('?view=config');
721 } 714 }
722 715
723 $themes = $this->getInstalledThemes(); 716 $themes = $this->getInstalledThemes();
724 $actualTheme = false; 717 $actualTheme = false;
725 718
726 foreach (array_keys($themes) as $theme) { 719 foreach (array_keys($themes) as $theme) {
727 if ($theme == $_POST['theme']) { 720 if ($theme == $_POST['theme']) {
728 $actualTheme = true; 721 $actualTheme = true;
729 break; 722 break;
730 } 723 }
731 } 724 }
732 725
733 if (! $actualTheme) { 726 if (! $actualTheme) {
734 $this->messages->add('e', _('that theme does not seem to be installed')); 727 $this->messages->add('e', _('that theme does not seem to be installed'));
735 Tools::redirect('?view=config'); 728 Tools::redirect('?view=config');
736 } 729 }
737 730
738 $this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']); 731 $this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']);
739 $this->messages->add('s', _('you have changed your theme preferences')); 732 $this->messages->add('s', _('you have changed your theme preferences'));
740 733
741 $currentConfig = $_SESSION['poche_user']->config; 734 $currentConfig = $_SESSION['poche_user']->config;
742 $currentConfig['theme'] = $_POST['theme']; 735 $currentConfig['theme'] = $_POST['theme'];
743 736
744 $_SESSION['poche_user']->setConfig($currentConfig); 737 $_SESSION['poche_user']->setConfig($currentConfig);
745 738
746 $this->emptyCache(); 739 $this->emptyCache();
747 740
748 Tools::redirect('?view=config'); 741 Tools::redirect('?view=config');
749 } 742 }
750 743
@@ -753,40 +746,40 @@ class Poche
753 # no data 746 # no data
754 if (empty($_POST['language'])) { 747 if (empty($_POST['language'])) {
755 } 748 }
756 749
757 # we are not going to change it to the current language... 750 # we are not going to change it to the current language...
758 if ($_POST['language'] == $this->getLanguage()) { 751 if ($_POST['language'] == $this->getLanguage()) {
759 $this->messages->add('w', _('still using the "' . $this->getLanguage() . '" language!')); 752 $this->messages->add('w', _('still using the "' . $this->getLanguage() . '" language!'));
760 Tools::redirect('?view=config'); 753 Tools::redirect('?view=config');
761 } 754 }
762 755
763 $languages = $this->getInstalledLanguages(); 756 $languages = $this->getInstalledLanguages();
764 $actualLanguage = false; 757 $actualLanguage = false;
765 758
766 foreach ($languages as $language) { 759 foreach ($languages as $language) {
767 if ($language['value'] == $_POST['language']) { 760 if ($language['value'] == $_POST['language']) {
768 $actualLanguage = true; 761 $actualLanguage = true;
769 break; 762 break;
770 } 763 }
771 } 764 }
772 765
773 if (! $actualLanguage) { 766 if (! $actualLanguage) {
774 $this->messages->add('e', _('that language does not seem to be installed')); 767 $this->messages->add('e', _('that language does not seem to be installed'));
775 Tools::redirect('?view=config'); 768 Tools::redirect('?view=config');
776 } 769 }
777 770
778 $this->store->updateUserConfig($this->user->getId(), 'language', $_POST['language']); 771 $this->store->updateUserConfig($this->user->getId(), 'language', $_POST['language']);
779 $this->messages->add('s', _('you have changed your language preferences')); 772 $this->messages->add('s', _('you have changed your language preferences'));
780 773
781 $currentConfig = $_SESSION['poche_user']->config; 774 $currentConfig = $_SESSION['poche_user']->config;
782 $currentConfig['language'] = $_POST['language']; 775 $currentConfig['language'] = $_POST['language'];
783 776
784 $_SESSION['poche_user']->setConfig($currentConfig); 777 $_SESSION['poche_user']->setConfig($currentConfig);
785 778
786 $this->emptyCache(); 779 $this->emptyCache();
787 780
788 Tools::redirect('?view=config'); 781 Tools::redirect('?view=config');
789 } 782 }
790 /** 783 /**
791 * get credentials from differents sources 784 * get credentials from differents sources
792 * it redirects the user to the $referer link 785 * it redirects the user to the $referer link
@@ -841,7 +834,7 @@ class Poche
841 /** 834 /**
842 * log out the poche user. It cleans the session. 835 * log out the poche user. It cleans the session.
843 * @todo add the return value 836 * @todo add the return value
844 * @return boolean 837 * @return boolean
845 */ 838 */
846 public function logout() 839 public function logout()
847 { 840 {
@@ -897,7 +890,7 @@ class Poche
897 * import from Pocket. poche needs a ./ril_export.html file 890 * import from Pocket. poche needs a ./ril_export.html file
898 * @todo add the return value 891 * @todo add the return value
899 * @param string $targetFile the file used for importing 892 * @param string $targetFile the file used for importing
900 * @return boolean 893 * @return boolean
901 */ 894 */
902 private function importFromPocket($targetFile) 895 private function importFromPocket($targetFile)
903 { 896 {
@@ -928,7 +921,7 @@ class Poche
928 $this->action('add_tag',$url,$last_id,true,false,$tags); 921 $this->action('add_tag',$url,$last_id,true,false,$tags);
929 } 922 }
930 } 923 }
931 924
932 # the second <ul> is for read links 925 # the second <ul> is for read links
933 $read = 1; 926 $read = 1;
934 } 927 }
@@ -943,7 +936,7 @@ class Poche
943 * import from Readability. poche needs a ./readability file 936 * import from Readability. poche needs a ./readability file
944 * @todo add the return value 937 * @todo add the return value
945 * @param string $targetFile the file used for importing 938 * @param string $targetFile the file used for importing
946 * @return boolean 939 * @return boolean
947 */ 940 */
948 private function importFromReadability($targetFile) 941 private function importFromReadability($targetFile)
949 { 942 {
@@ -1000,7 +993,7 @@ class Poche
1000 /** 993 /**
1001 * import from Poche exported file 994 * import from Poche exported file
1002 * @param string $targetFile the file used for importing 995 * @param string $targetFile the file used for importing
1003 * @return boolean 996 * @return boolean
1004 */ 997 */
1005 private function importFromPoche($targetFile) 998 private function importFromPoche($targetFile)
1006 { 999 {
@@ -1020,12 +1013,12 @@ class Poche
1020 $url = new Url(base64_encode($value['url'])); 1013 $url = new Url(base64_encode($value['url']));
1021 $favorite = ($value['is_fav'] == -1); 1014 $favorite = ($value['is_fav'] == -1);
1022 $archive = ($value['is_read'] == -1); 1015 $archive = ($value['is_read'] == -1);
1023 1016
1024 # we can add the url 1017 # we can add the url
1025 if (!is_null($url) && $url->isCorrect()) { 1018 if (!is_null($url) && $url->isCorrect()) {
1026 1019
1027 $this->action('add', $url, 0, TRUE); 1020 $this->action('add', $url, 0, TRUE);
1028 1021
1029 $count++; 1022 $count++;
1030 if ($favorite) { 1023 if ($favorite) {
1031 $last_id = $this->store->getLastId($sequence); 1024 $last_id = $this->store->getLastId($sequence);
@@ -1036,7 +1029,7 @@ class Poche
1036 $this->action('toggle_archive', $url, $last_id, TRUE); 1029 $this->action('toggle_archive', $url, $last_id, TRUE);
1037 } 1030 }
1038 } 1031 }
1039 1032
1040 } 1033 }
1041 1034
1042 unlink($targetFile); 1035 unlink($targetFile);
@@ -1047,37 +1040,115 @@ class Poche
1047 1040
1048 /** 1041 /**
1049 * import datas into your poche 1042 * import datas into your poche
1050 * @param string $from name of the service to import : pocket, instapaper or readability 1043 * @return boolean
1051 * @todo add the return value
1052 * @return boolean
1053 */ 1044 */
1054 public function import($from) 1045 public function import() {
1055 { 1046
1056 $providers = array( 1047 if ( isset($_FILES['file']) ) {
1057 'pocket' => 'importFromPocket', 1048 // assume, that file is in json format
1058 'readability' => 'importFromReadability', 1049 $str_data = file_get_contents($_FILES['file']['tmp_name']);
1059 'instapaper' => 'importFromInstapaper', 1050 $data = json_decode($str_data, true);
1060 'poche' => 'importFromPoche', 1051
1061 ); 1052 if ( $data === null ) {
1062 1053 //not json - assume html
1063 if (! isset($providers[$from])) { 1054 $html = new simple_html_dom();
1064 $this->messages->add('e', _('Unknown import provider.')); 1055 $html->load_file($_FILES['file']['tmp_name']);
1065 Tools::redirect(); 1056 $data = array();
1057 $read = 0;
1058 foreach (array('ol','ul') as $list) {
1059 foreach ($html->find($list) as $ul) {
1060 foreach ($ul->find('li') as $li) {
1061 $tmpEntry = array();
1062 $a = $li->find('a');
1063 $tmpEntry['url'] = $a[0]->href;
1064 $tmpEntry['tags'] = $a[0]->tags;
1065 $tmpEntry['is_read'] = $read;
1066 if ($tmpEntry['url']) {
1067 $data[] = $tmpEntry;
1068 }
1069 }
1070 # the second <ol/ul> is for read links
1071 $read = ((sizeof($data) && $read)?0:1);
1072 }
1073 }
1066 } 1074 }
1067 1075
1068 $targetFile = CACHE . '/' . constant(strtoupper($from) . '_FILE'); 1076 $i = 0; //counter for articles inserted
1069 1077 foreach ($data as $record) {
1070 if (! file_exists($targetFile)) { 1078 //echo '<pre>';
1071 $this->messages->add('e', _('Could not find required "' . $targetFile . '" import file.')); 1079 //var_dump($record);
1072 Tools::redirect(); 1080 // foreach ($record as $key=>$val) {
1081 // echo "\n=================\n$i: $key: $val\n";
1082 // }
1083 // exit;
1084
1085 $url = trim($record['url']);
1086 if ( $url ) {
1087 $title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ').'</a> <a href="./?import">'._('click to finish import').'</a><a>');
1088 $body = (isset($record['content']) ? $record['content'] : '');
1089 $isRead = (isset($record['is_read']) ? intval($record['is_read']) : 0);
1090 $isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : 0);
1091 //insert new record
1092 $id = $this->store->add($url, $title, $body, $this->user->getId(), $isFavorite, $isRead);
1093 if ( $id ) {
1094 //increment no of records inserted
1095 $i++;
1096 if ( isset($record['tags']) && trim($record['tags']) ) {
1097 //@TODO: set tags
1098
1099 }
1100 }
1101 }
1102 }
1103
1104 if ( $i > 0 ) {
1105 $this->messages->add('s', _('Articles inserted: ').$i._('. Please note, that some may be marked as "read".'));
1073 } 1106 }
1074 1107 }
1075 $this->$providers[$from]($targetFile); 1108 //file parsing finished here
1109
1110 //now download article contents if any
1111
1112 //check if we need to download any content
1113 $recordsDownloadRequired = $this->store->retrieveUnfetchedEntriesCount($this->user->getId());
1114 if ( $recordsDownloadRequired == 0 ) {
1115 //nothing to download
1116 $this->messages->add('s', _('Import finished.'));
1117 Tools::redirect();
1118 }
1119 else {
1120 //if just inserted - don't download anything, download will start in next reload
1121 if ( !isset($_FILES['file']) ) {
1122 //download next batch
1123 $items = $this->store->retrieveUnfetchedEntries($this->user->getId(), IMPORT_LIMIT);
1124
1125 $config = HTMLPurifier_Config::createDefault();
1126 $config->set('Cache.SerializerPath', CACHE);
1127 $purifier = new HTMLPurifier($config);
1128
1129 foreach ($items as $item) {
1130 $url = new Url(base64_encode($item['url']));
1131 $content = Tools::getPageContent($url);
1132
1133 $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
1134 $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
1135
1136 //clean content to prevent xss attack
1137 $title = $purifier->purify($title);
1138 $body = $purifier->purify($body);
1139
1140 $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
1141 }
1142
1143 }
1144 }
1145
1146 return array('includeImport'=>true, 'import'=>array('recordsDownloadRequired'=>$recordsDownloadRequired, 'recordsUnderDownload'=> IMPORT_LIMIT, 'delay'=> IMPORT_DELAY * 1000) );
1076 } 1147 }
1077 1148
1078 public function uploadFile() { 1149 public function uploadFile() {
1079 if(isset($_FILES['file'])) 1150 if (isset($_FILES['file']))
1080 { 1151 {
1081 $dir = CACHE . '/'; 1152 $dir = CACHE . '/';
1082 $file = basename($_FILES['file']['name']); 1153 $file = basename($_FILES['file']['name']);
1083 if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) { 1154 if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) {
@@ -1087,7 +1158,7 @@ class Poche
1087 $this->messages->add('e', _('Error while importing file. Do you have access to upload it?')); 1158 $this->messages->add('e', _('Error while importing file. Do you have access to upload it?'));
1088 } 1159 }
1089 } 1160 }
1090 1161
1091 Tools::redirect('?view=config'); 1162 Tools::redirect('?view=config');
1092 } 1163 }
1093 1164
@@ -1099,7 +1170,7 @@ class Poche
1099 { 1170 {
1100 $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json"; 1171 $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
1101 header('Content-Disposition: attachment; filename='.$filename); 1172 header('Content-Disposition: attachment; filename='.$filename);
1102 1173
1103 $entries = $this->store->retrieveAll($this->user->getId()); 1174 $entries = $this->store->retrieveAll($this->user->getId());
1104 echo $this->tpl->render('export.twig', array( 1175 echo $this->tpl->render('export.twig', array(
1105 'export' => Tools::renderJson($entries), 1176 'export' => Tools::renderJson($entries),
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php
index ad451fc6..a130e94b 100755
--- a/inc/poche/Tools.class.php
+++ b/inc/poche/Tools.class.php
@@ -7,7 +7,7 @@
7 * @copyright 2013 7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file 8 * @license http://www.wtfpl.net/ see COPYING file
9 */ 9 */
10 10
11class Tools 11class Tools
12{ 12{
13 public static function initPhp() 13 public static function initPhp()
@@ -42,7 +42,7 @@ class Tools
42 && (strtolower($_SERVER['HTTPS']) == 'on')) 42 && (strtolower($_SERVER['HTTPS']) == 'on'))
43 || (isset($_SERVER["SERVER_PORT"]) 43 || (isset($_SERVER["SERVER_PORT"])
44 && $_SERVER["SERVER_PORT"] == '443') // HTTPS detection. 44 && $_SERVER["SERVER_PORT"] == '443') // HTTPS detection.
45 || (isset($_SERVER["SERVER_PORT"]) //Custom HTTPS port detection 45 || (isset($_SERVER["SERVER_PORT"]) //Custom HTTPS port detection
46 && $_SERVER["SERVER_PORT"] == SSL_PORT) 46 && $_SERVER["SERVER_PORT"] == SSL_PORT)
47 || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) 47 || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
48 && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'); 48 && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
@@ -148,7 +148,7 @@ class Tools
148 ); 148 );
149 149
150 # only download page lesser than 4MB 150 # only download page lesser than 4MB
151 $data = @file_get_contents($url, false, $context, -1, 4000000); 151 $data = @file_get_contents($url, false, $context, -1, 4000000);
152 152
153 if (isset($http_response_header) and isset($http_response_header[0])) { 153 if (isset($http_response_header) and isset($http_response_header[0])) {
154 $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE)); 154 $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE));
@@ -200,7 +200,7 @@ class Tools
200 } 200 }
201 } 201 }
202 202
203 public static function encodeString($string) 203 public static function encodeString($string)
204 { 204 {
205 return sha1($string . SALT); 205 return sha1($string . SALT);
206 } 206 }
diff --git a/inc/poche/config.inc.php.new b/inc/poche/config.inc.php.new
index 8d52497b..83b3c4c0 100755
--- a/inc/poche/config.inc.php.new
+++ b/inc/poche/config.inc.php.new
@@ -52,12 +52,8 @@ define ('CACHE', ROOT . '/cache');
52 52
53define ('PAGINATION', '10'); 53define ('PAGINATION', '10');
54 54
55define ('POCKET_FILE', '/ril_export.html'); 55//limit for download of articles during import
56define ('READABILITY_FILE', '/readability'); 56define ('IMPORT_LIMIT', 5);
57define ('INSTAPAPER_FILE', '/instapaper-export.html'); 57//delay between downloads (in sec)
58define ('POCHE_FILE', '/poche-export'); 58define ('IMPORT_DELAY', 5);
59 59
60define ('IMPORT_POCKET_FILE', ROOT . POCKET_FILE);
61define ('IMPORT_READABILITY_FILE', ROOT . READABILITY_FILE);
62define ('IMPORT_INSTAPAPER_FILE', ROOT . INSTAPAPER_FILE);
63define ('IMPORT_POCHE_FILE', ROOT . POCHE_FILE); \ No newline at end of file