]>
git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/poche/Poche.class.php
3 * wallabag, self hostable application allowing you to not miss any content anymore
6 * @author Nicolas Lœuillet <nicolas@loeuillet.org>
8 * @license http://opensource.org/licenses/MIT see COPYING file
42 public function __construct ()
47 private function init ()
51 $pocheUser = Session
:: getParam ( 'poche_user' );
53 if ( $pocheUser && $pocheUser != array ()) {
54 $this- > user
= $pocheUser ;
56 // fake user, just for install & login screens
57 $this- > user
= new User ();
58 $this- > user
-> setConfig ( $this- > getDefaultConfig ());
61 $this- > pagination
= new Paginator ( $this- > user
-> getConfigValue ( 'pager' ), 'p' );
62 $this- > language
= new Language ( $this );
63 $this- > tpl
= new Template ( $this );
64 $this- > store
= new Database ();
65 $this- > messages
= new Messages ();
66 $this- > routing
= new Routing ( $this );
71 $this- > routing
-> run ();
77 public function createNewUser ( $username , $password , $email = "" , $internalRegistration = false )
79 if (! empty ( $username ) && ! empty ( $password )){
80 $newUsername = filter_var ( $username , FILTER_SANITIZE_STRING
);
81 $email = filter_var ( $email , FILTER_SANITIZE_STRING
);
82 if (! $this- > store
-> userExists ( $newUsername )){
83 if ( $this- > store
-> install ( $newUsername , Tools
:: encodeString ( $password . $newUsername ), $email )) {
84 if ( SEND_CONFIRMATION_EMAIL
&& function_exists ( 'mail' )) {
85 // if internal registration
86 $body_internal = "Hi, \r\n\r\n Someone just created an account for you on " . Tools
:: getPocheUrl () . ". \r\n Have fun with it !" ;
87 // if external (public) registration
88 $body = "Hi, \r\n\r\n You've just created an account on " . Tools
:: getPocheUrl () . ". \r\n Have fun with it !" ;
89 $body = $internalRegistration ? $body_internal : $body ;
90 $body = wordwrap ( $body , 70 , " \r\n " ); // cut lines with more than 70 caracters (MIME standard)
91 if ( mail ( $email , sprintf ( _ ( 'Your new wallabag account on ' ), Tools
:: getPocheUrl ()), $body , 'X-Mailer: PHP/' . phpversion ())) {
92 Tools
:: logm ( 'The user ' . $newUsername . ' has been emailed' );
93 $this- > messages
-> add ( 'i' , sprintf ( _ ( 'The new user %1 $s has been sent an email at %2 $s .' ), $newUsername , $email ));
96 Tools
:: logm ( 'A problem has been encountered while sending an email' );
97 $this- > messages
-> add ( 'e' , _ ( 'A problem has been encountered while sending an email' ));
100 Tools
:: logm ( 'The user has been created, but the server did not authorize sending emails' );
101 $this- > messages
-> add ( 'i' , _ ( 'The server did not authorize sending an email' ));
103 Tools
:: logm ( 'The new user ' . $newUsername . ' has been installed' );
104 $this- > messages
-> add ( 's' , sprintf ( _ ( 'The new user %s has been installed. Do you want to <a href="?logout">logout ?</a>' ), $newUsername ));
108 Tools
:: logm ( 'error during adding new user' );
113 $this- > messages
-> add ( 'e' , sprintf ( _ ( 'Error : An user with the name %s already exists !' ), $newUsername ));
114 Tools
:: logm ( 'An user with the name ' . $newUsername . ' already exists !' );
121 * Delete an existing user
123 public function deleteUser ( $password )
125 if ( $this- > store
-> listUsers () > 1 ) {
126 if ( Tools
:: encodeString ( $password . $this- > user
-> getUsername ()) == $this- > store
-> getUserPassword ( $this- > user
-> getId ())) {
127 $username = $this- > user
-> getUsername ();
128 $this- > store
-> deleteUserConfig ( $this- > user
-> getId ());
129 Tools
:: logm ( 'The configuration for user ' . $username . ' has been deleted !' );
130 $this- > store
-> deleteTagsEntriesAndEntries ( $this- > user
-> getId ());
131 Tools
:: logm ( 'The entries for user ' . $username . ' has been deleted !' );
132 $this- > store
-> deleteUser ( $this- > user
-> getId ());
133 Tools
:: logm ( 'User ' . $username . ' has been completely deleted !' );
135 Tools
:: logm ( 'logout' );
137 $this- > messages
-> add ( 's' , sprintf ( _ ( 'User %s has been successfully deleted !' ), $username ));
140 Tools
:: logm ( 'Bad password !' );
141 $this- > messages
-> add ( 'e' , _ ( 'Error : The password is wrong !' ));
145 Tools
:: logm ( 'Only user !' );
146 $this- > messages
-> add ( 'e' , _ ( 'Error : You are the only user, you cannot delete your account !' ));
150 public function getDefaultConfig ()
153 'pager' => PAGINATION
,
155 'theme' => DEFAULT_THEME
160 * Call action (mark as fav, archive, delete, etc.)
162 public function action ( $action , Url
$url , $id = 0 , $import = FALSE , $autoclose = FALSE , $tags = null )
167 $content = Tools
:: getPageContent ( $url );
168 $title = ( $content [ 'rss' ][ 'channel' ][ 'item' ][ 'title' ] != '' ) ? $content [ 'rss' ][ 'channel' ][ 'item' ][ 'title' ] : _ ( 'Untitled' );
169 $body = $content [ 'rss' ][ 'channel' ][ 'item' ][ 'description' ];
171 // clean content from prevent xss attack
172 $purifier = $this- > _getPurifier ();
173 $title = $purifier- > purify ( $title );
174 $body = $purifier- > purify ( $body );
176 //search for possible duplicate
178 $duplicate = $this- > store
-> retrieveOneByURL ( $url- > getUrl (), $this- > user
-> getId ());
180 $last_id = $this- > store
-> add ( $url- > getUrl (), $title , $body , $this- > user
-> getId ());
182 Tools
:: logm ( 'add link ' . $url- > getUrl ());
183 if ( DOWNLOAD_PICTURES
) {
184 $content = Picture
:: filterPicture ( $body , $url- > getUrl (), $last_id );
185 Tools
:: logm ( 'updating content article' );
186 $this- > store
-> updateContent ( $last_id , $content , $this- > user
-> getId ());
189 if ( $duplicate != NULL ) {
190 // duplicate exists, so, older entry needs to be deleted (as new entry should go to the top of list), BUT favorite mark and tags should be preserved
191 Tools
:: logm ( 'link ' . $url- > getUrl () . ' is a duplicate' );
192 // 1) - preserve tags and favorite, then drop old entry
193 $this- > store
-> reassignTags ( $duplicate [ 'id' ], $last_id );
194 if ( $duplicate [ 'is_fav' ]) {
195 $this- > store
-> favoriteById ( $last_id , $this- > user
-> getId ());
197 if ( $this- > store
-> deleteById ( $duplicate [ 'id' ], $this- > user
-> getId ())) {
198 Tools
:: logm ( 'previous link ' . $url- > getUrl () . ' entry deleted' );
202 // if there are tags, add them to the new article
203 if ( isset ( $_GET [ 'tags' ])) {
204 $_POST [ 'value' ] = $_GET [ 'tags' ];
205 $_POST [ 'entry_id' ] = $last_id ;
206 $this- > action ( 'add_tag' , $url );
209 $this- > messages
-> add ( 's' , _ ( 'the link has been added successfully' ));
212 $this- > messages
-> add ( 'e' , _ ( 'error during insertion : the link wasn \' t added' ));
213 Tools
:: logm ( 'error during insertion : the link wasn \' t added ' . $url- > getUrl ());
216 if ( $autoclose == TRUE ) {
217 Tools
:: redirect ( '?view=home&closewin=true' );
219 Tools
:: redirect ( '?view=home' );
224 if ( isset ( $_GET [ 'search' ])) {
225 //when we want to apply a delete to a search
226 $tags = array ( $_GET [ 'search' ]);
227 $allentry_ids = $this- > store
-> search ( $tags [ 0 ], $this- > user
-> getId ());
228 $entry_ids = array ();
229 foreach ( $allentry_ids as $eachentry ) {
230 $entry_ids [] = $eachentry [ 0 ];
232 } else { // delete a single article
233 $entry_ids = array ( $id );
235 foreach ( $entry_ids as $id ) {
236 $msg = 'delete link #' . $id ;
237 if ( $this- > store
-> deleteById ( $id , $this- > user
-> getId ())) {
238 if ( DOWNLOAD_PICTURES
) {
239 Picture
:: removeDirectory ( ABS_PATH
. $id );
241 $this- > messages
-> add ( 's' , _ ( 'the link has been deleted successfully' ));
244 $this- > messages
-> add ( 'e' , _ ( 'the link wasn \' t deleted' ));
245 $msg = 'error : can \' t delete link #' . $id ;
249 Tools
:: redirect ( '?' );
252 $this- > store
-> favoriteById ( $id , $this- > user
-> getId ());
253 Tools
:: logm ( 'mark as favorite link #' . $id );
254 if ( Tools
:: isAjaxRequest () ) {
262 case 'toggle_archive' :
263 if ( isset ( $_GET [ 'tag_id' ])) {
264 //when we want to archive a whole tag
265 $tag_id = $_GET [ 'tag_id' ];
266 $allentry_ids = $this- > store
-> retrieveEntriesByTag ( $tag_id , $this- > user
-> getId ());
267 $entry_ids = array ();
268 foreach ( $allentry_ids as $eachentry ) {
269 $entry_ids [] = $eachentry [ 0 ];
271 } else { //archive a single article
272 $entry_ids = array ( $id );
274 foreach ( $entry_ids as $id ) {
275 $this- > store
-> archiveById ( $id , $this- > user
-> getId ());
276 Tools
:: logm ( 'archive link #' . $id );
278 if ( Tools
:: isAjaxRequest () ) {
287 $this- > store
-> archiveAll ( $this- > user
-> getId ());
288 Tools
:: logm ( 'archive all links' );
292 if ( isset ( $_GET [ 'search' ])) {
293 //when we want to apply a tag to a search
294 $tags = array ( $_GET [ 'search' ]);
295 $allentry_ids = $this- > store
-> search ( $tags [ 0 ], $this- > user
-> getId ());
296 $entry_ids = array ();
297 foreach ( $allentry_ids as $eachentry ) {
298 $entry_ids [] = $eachentry [ 0 ];
300 } else { //add a tag to a single article
301 $tags = explode ( ',' , $_POST [ 'value' ]);
302 $entry_ids = array ( $_POST [ 'entry_id' ]);
304 foreach ( $entry_ids as $entry_id ) {
305 $entry = $this- > store
-> retrieveOneById ( $entry_id , $this- > user
-> getId ());
307 $this- > messages
-> add ( 'e' , _ ( 'Article not found!' ));
308 Tools
:: logm ( 'error : article not found' );
311 //get all already set tags to preven duplicates
312 $already_set_tags = array ();
313 $entry_tags = $this- > store
-> retrieveTagsByEntry ( $entry_id );
314 foreach ( $entry_tags as $tag ) {
315 $already_set_tags [] = $tag [ 'value' ];
317 foreach ( $tags as $key => $tag_value ) {
318 $value = trim ( $tag_value );
319 if ( $value && ! in_array ( $value , $already_set_tags )) {
320 $tag = $this- > store
-> retrieveTagByValue ( $value );
323 $tag = $this- > store
-> createTag ( $value );
325 if ( STORAGE
== 'postgres' ) {
326 $sequence = 'tags_id_seq' ;
328 $tag_id = $this- > store
-> getLastId ( $sequence );
331 $tag_id = $tag [ 'id' ];
334 # we assign the tag to the article
335 $this- > store
-> setTagToEntry ( $tag_id , $entry_id );
339 $this- > messages
-> add ( 's' , _ ( 'The tag has been applied successfully' ));
340 Tools
:: logm ( 'The tag has been applied successfully' );
344 $tag_id = $_GET [ 'tag_id' ];
345 $entry = $this- > store
-> retrieveOneById ( $id , $this- > user
-> getId ());
347 $this- > messages
-> add ( 'e' , _ ( 'Article not found!' ));
348 Tools
:: logm ( 'error : article not found' );
351 $this- > store
-> removeTagForEntry ( $id , $tag_id );
352 Tools
:: logm ( 'tag entry deleted' );
353 if ( $this- > store
-> cleanUnusedTag ( $tag_id )) {
354 Tools
:: logm ( 'tag deleted' );
356 $this- > messages
-> add ( 's' , _ ( 'The tag has been successfully deleted' ));
360 case 'reload_article' :
361 Tools
:: logm ( 'reload article' );
363 $entry = $this- > store
-> retrieveOneById ( $id , $this- > user
-> getId ());
364 Tools
:: logm ( 'reload url ' . $entry [ 'url' ]);
365 $url = new Url ( base64_encode ( $entry [ 'url' ]));
366 $this- > action ( 'add' , $url );
369 /* For some unknown reason I can't get displayView() to work here (it redirects to home view afterwards). So here's a dirty fix which redirects directly to URL */
372 while ( $this- > store
-> retrieveOneById ( $id , $this- > user
-> getId ()) == null ) {
373 $count = $this- > store
-> getEntriesByViewCount ( $view , $this- > user
-> getId ());
374 $id = rand ( 1 , $count );
376 Tools
:: logm ( 'get a random article' );
377 Tools
:: redirect ( '?view=view&id=' . $id );
378 //$this->displayView('view', $id);
385 function displayView ( $view , $id = 0 )
394 $dev_infos = $this- > _getPocheVersion ( 'dev' );
395 $dev = trim ( $dev_infos [ 0 ]);
396 $check_time_dev = date ( 'd-M-Y H:i' , $dev_infos [ 1 ]);
397 $prod_infos = $this- > _getPocheVersion ( 'prod' );
398 $prod = trim ( $prod_infos [ 0 ]);
399 $check_time_prod = date ( 'd-M-Y H:i' , $prod_infos [ 1 ]);
400 $compare_dev = version_compare ( POCHE
, $dev );
401 $compare_prod = version_compare ( POCHE
, $prod );
402 $themes = $this- > tpl
-> getInstalledThemes ();
403 $languages = $this- > language
-> getInstalledLanguages ();
404 $token = $this- > user
-> getConfigValue ( 'token' );
405 $http_auth = ( isset ( $_SERVER [ 'PHP_AUTH_USER' ]) || isset ( $_SERVER [ 'REMOTE_USER' ])) ? true : false ;
406 $only_user = ( $this- > store
-> listUsers () > 1 ) ? false : true ;
409 'languages' => $languages ,
412 'check_time_dev' => $check_time_dev ,
413 'check_time_prod' => $check_time_prod ,
414 'compare_dev' => $compare_dev ,
415 'compare_prod' => $compare_prod ,
417 'user_id' => $this- > user
-> getId (),
418 'http_auth' => $http_auth ,
419 'only_user' => $only_user
421 Tools
:: logm ( 'config view' );
425 $entry = $this- > store
-> retrieveOneById ( $id , $this- > user
-> getId ());
427 $this- > messages
-> add ( 'e' , _ ( 'Article not found!' ));
428 Tools
:: logm ( 'error : article not found' );
431 $tags = $this- > store
-> retrieveTagsByEntry ( $id );
439 $token = $this- > user
-> getConfigValue ( 'token' );
440 //if term is set - search tags for this term
441 $term = Tools
:: checkVar ( 'term' );
442 $tags = $this- > store
-> retrieveAllTags ( $this- > user
-> getId (), $term );
443 if ( Tools
:: isAjaxRequest ()) {
445 foreach ( $tags as $tag ) {
446 $result [] = $tag [ 'value' ];
448 echo json_encode ( $result );
453 'user_id' => $this- > user
-> getId (),
458 if ( isset ( $_GET [ 'search' ])) {
459 $search = filter_var ( $_GET [ 'search' ], FILTER_SANITIZE_STRING
);
460 $tpl_vars [ 'entries' ] = $this- > store
-> search ( $search , $this- > user
-> getId ());
461 $count = count ( $tpl_vars [ 'entries' ]);
462 $this- > pagination
-> set_total ( $count );
463 $page_links = str_replace ( array ( 'previous' , 'next' ), array ( _ ( 'previous' ), _ ( 'next' )),
464 $this- > pagination
-> page_links ( '?view=' . $view . '?search=' . $search . '&sort=' . $_SESSION [ 'sort' ] . '&' ));
465 $tpl_vars [ 'page_links' ] = $page_links ;
466 $tpl_vars [ 'nb_results' ] = $count ;
467 $tpl_vars [ 'searchterm' ] = $search ;
471 $entry = $this- > store
-> retrieveOneById ( $id , $this- > user
-> getId ());
472 if ( $entry != NULL ) {
473 Tools
:: logm ( 'view link #' . $id );
474 $content = $entry [ 'content' ];
475 if ( function_exists ( 'tidy_parse_string' )) {
476 $tidy = tidy_parse_string ( $content , array ( 'indent' => true , 'show-body-only' => true ), 'UTF8' );
477 $tidy- > cleanRepair ();
478 $content = $tidy- > value
;
484 $flattr = new FlattrItem ();
485 $flattr- > checkItem ( $entry [ 'url' ], $entry [ 'id' ]);
489 $tags = $this- > store
-> retrieveTagsByEntry ( $entry [ 'id' ]);
493 'content' => $content ,
499 Tools
:: logm ( 'error in view call : entry is null' );
502 default : # home, favorites, archive and tag views
507 'listmode' => ( isset ( $_COOKIE [ 'listmode' ]) ? true : false ),
510 //if id is given - we retrieve entries by tag: id is tag id
512 $tpl_vars [ 'tag' ] = $this- > store
-> retrieveTag ( $id , $this- > user
-> getId ());
513 $tpl_vars [ 'id' ] = intval ( $id );
516 $count = $this- > store
-> getEntriesByViewCount ( $view , $this- > user
-> getId (), $id );
519 $this- > pagination
-> set_total ( $count );
520 $page_links = str_replace ( array ( 'previous' , 'next' ), array ( _ ( 'previous' ), _ ( 'next' )),
521 $this- > pagination
-> page_links ( '?view=' . $view . '&sort=' . $_SESSION [ 'sort' ] . (( $id )? '&id=' . $id : '' ) . '&' ));
522 $tpl_vars [ 'entries' ] = $this- > store
-> getEntriesByView ( $view , $this- > user
-> getId (), $this- > pagination
-> get_limit (), $id );
523 $tpl_vars [ 'page_links' ] = $page_links ;
524 $tpl_vars [ 'nb_results' ] = $count ;
526 Tools
:: logm ( 'display ' . $view . ' view' );
534 * update the password of the current user.
535 * if MODE_DEMO is TRUE, the password can't be updated.
536 * @todo add the return value
537 * @todo set the new password in function header like this updatePassword($newPassword)
540 public function updatePassword ( $password , $confirmPassword )
543 $this- > messages
-> add ( 'i' , _ ( 'in demo mode, you can \' t update your password' ));
544 Tools
:: logm ( 'in demo mode, you can \' t do this' );
545 Tools
:: redirect ( '?view=config' );
548 if ( isset ( $password ) && isset ( $confirmPassword )) {
549 if ( $password == $confirmPassword && ! empty ( $password )) {
550 $this- > messages
-> add ( 's' , _ ( 'your password has been updated' ));
551 $this- > store
-> updatePassword ( $this- > user
-> getId (), Tools
:: encodeString ( $password . $this- > user
-> getUsername ()));
553 Tools
:: logm ( 'password updated' );
557 $this- > messages
-> add ( 'e' , _ ( 'the two fields have to be filled & the password must be the same in the two fields' ));
558 Tools
:: redirect ( '?view=config' );
565 * Get credentials from differents sources
566 * It redirects the user to the $referer link
570 private function credentials ()
572 if ( isset ( $_SERVER [ 'PHP_AUTH_USER' ])) {
573 return array ( $_SERVER [ 'PHP_AUTH_USER' ], 'php_auth' , true );
575 if (! empty ( $_POST [ 'login' ]) && ! empty ( $_POST [ 'password' ])) {
576 return array ( $_POST [ 'login' ], $_POST [ 'password' ], false );
578 if ( isset ( $_SERVER [ 'REMOTE_USER' ])) {
579 return array ( $_SERVER [ 'REMOTE_USER' ], 'http_auth' , true );
582 return array ( false , false , false );
586 * checks if login & password are correct and save the user in session.
587 * it redirects the user to the $referer link
588 * @param string $referer the url to redirect after login
589 * @todo add the return value
592 public function login ( $referer )
594 list ( $login , $password , $isauthenticated )= $this- > credentials ();
595 if ( $login === false || $password === false ) {
596 $this- > messages
-> add ( 'e' , _ ( 'login failed: you have to fill all fields' ));
597 Tools
:: logm ( 'login failed' );
600 if (! empty ( $login ) && ! empty ( $password )) {
601 $user = $this- > store
-> login ( $login , Tools
:: encodeString ( $password . $login ), $isauthenticated );
602 if ( $user != array ()) {
603 # Save login into Session
604 $longlastingsession = isset ( $_POST [ 'longlastingsession' ]);
605 $passwordTest = ( $isauthenticated ) ? $user [ 'password' ] : Tools
:: encodeString ( $password . $login );
606 Session
:: login ( $user [ 'username' ], $user [ 'password' ], $login , $passwordTest , $longlastingsession , array ( 'poche_user' => new User ( $user )));
609 $language = $user [ 'config' ][ 'language' ];
610 @ putenv ( 'LC_ALL=' . $language );
611 setlocale ( LC_ALL
, $language );
612 bindtextdomain ( $language , LOCALE
);
613 textdomain ( $language );
615 $this- > messages
-> add ( 's' , _ ( 'welcome to your wallabag' ));
616 Tools
:: logm ( 'login successful' );
617 Tools
:: redirect ( $referer );
619 $this- > messages
-> add ( 'e' , _ ( 'login failed: bad login or password' ));
620 // log login failure in web server log to allow fail2ban usage
621 error_log ( 'user ' . $login . ' authentication failure' );
622 Tools
:: logm ( 'login failed' );
628 * log out the poche user. It cleans the session.
629 * @todo add the return value
632 public function logout ()
634 $this- > user
= array ();
636 Tools
:: logm ( 'logout' );
641 * import datas into your wallabag
645 public function import () {
647 if ( isset ( $_FILES [ 'file' ]) && $_FILES [ 'file' ][ 'tmp_name' ] ) {
648 Tools
:: logm ( 'Import stated: parsing file' );
650 // assume, that file is in json format
651 $str_data = file_get_contents ( $_FILES [ 'file' ][ 'tmp_name' ]);
652 $data = json_decode ( $str_data , true );
654 if ( $data === null ) {
655 //not json - assume html
656 $html = new simple_html_dom ();
657 $html- > load_file ( $_FILES [ 'file' ][ 'tmp_name' ]);
660 foreach ( array ( 'ol' , 'ul' ) as $list ) {
661 foreach ( $html- > find ( $list ) as $ul ) {
662 foreach ( $ul- > find ( 'li' ) as $li ) {
665 $tmpEntry [ 'url' ] = $a [ 0 ]-> href
;
666 $tmpEntry [ 'tags' ] = $a [ 0 ]-> tags
;
667 $tmpEntry [ 'is_read' ] = $read ;
668 if ( $tmpEntry [ 'url' ]) {
672 # the second <ol/ul> is for read links
673 $read = (( sizeof ( $data ) && $read )? 0 : 1 );
678 // for readability structure
680 foreach ( $data as $record ) {
681 if ( is_array ( $record )) {
683 foreach ( $record as $record2 ) {
684 if ( is_array ( $record2 )) {
691 $urlsInserted = array (); //urls of articles inserted
692 foreach ( $data as $record ) {
693 $url = trim ( isset ( $record [ 'article__url' ]) ? $record [ 'article__url' ] : ( isset ( $record [ 'url' ]) ? $record [ 'url' ] : '' ));
694 if ( $url and ! in_array ( $url , $urlsInserted )) {
695 $title = ( isset ( $record [ 'title' ]) ? $record [ 'title' ] : _ ( 'Untitled - Import - ' ) . '</a> <a href="./?import">' . _ ( 'click to finish import' ) . '</a><a>' );
696 $body = ( isset ( $record [ 'content' ]) ? $record [ 'content' ] : '' );
697 $isRead = ( isset ( $record [ 'is_read' ]) ? intval ( $record [ 'is_read' ]) : ( isset ( $record [ 'archive' ]) ? intval ( $record [ 'archive' ]) : 0 ));
698 $isFavorite = ( isset ( $record [ 'is_fav' ]) ? intval ( $record [ 'is_fav' ]) : ( isset ( $record [ 'favorite' ]) ? intval ( $record [ 'favorite' ]) : 0 ));
702 $id = $this- > store
-> add ( $url , $title , $body , $this- > user
-> getId () , $isFavorite , $isRead );
704 $urlsInserted [] = $url ; //add
705 if ( isset ( $record [ 'tags' ]) && trim ( $record [ 'tags' ])) {
707 $tags = explode ( ',' , $record [ 'tags' ]);
708 foreach ( $tags as $tag ) {
710 $tag_id = $this- > store
-> retrieveTagByValue ( $tag );
712 $this- > store
-> setTagToEntry ( $tag_id [ 'id' ], $entry_id );
714 $this- > store
-> createTag ( $tag );
715 $tag_id = $this- > store
-> retrieveTagByValue ( $tag );
716 $this- > store
-> setTagToEntry ( $tag_id [ 'id' ], $entry_id );
725 $i = sizeof ( $urlsInserted );
727 $this- > messages
-> add ( 's' , _ ( 'Articles inserted: ' ) . $i . _ ( '. Please note, that some may be marked as "read".' ));
730 Tools
:: logm ( 'Import of articles finished: ' . $i . ' articles added (w/o content if not provided).' );
733 $this- > messages
-> add ( 's' , _ ( 'Did you forget to select a file?' ));
735 // file parsing finished here
736 // now download article contents if any
737 // check if we need to download any content
739 $recordsDownloadRequired = $this- > store
-> retrieveUnfetchedEntriesCount ( $this- > user
-> getId ());
741 if ( $recordsDownloadRequired == 0 ) {
743 // nothing to download
745 $this- > messages
-> add ( 's' , _ ( 'Import finished.' ));
746 Tools
:: logm ( 'Import finished completely' );
751 // if just inserted - don't download anything, download will start in next reload
753 if (! isset ( $_FILES [ 'file' ])) {
755 // download next batch
757 Tools
:: logm ( 'Fetching next batch of articles...' );
758 $items = $this- > store
-> retrieveUnfetchedEntries ( $this- > user
-> getId () , IMPORT_LIMIT
);
759 $purifier = $this- > _getPurifier ();
760 foreach ( $items as $item ) {
761 $url = new Url ( base64_encode ( $item [ 'url' ]));
762 if ( $url- > isCorrect () )
764 Tools
:: logm ( 'Fetching article ' . $item [ 'id' ]);
765 $content = Tools
:: getPageContent ( $url );
766 $title = (( $content [ 'rss' ][ 'channel' ][ 'item' ][ 'title' ] != '' ) ? $content [ 'rss' ][ 'channel' ][ 'item' ][ 'title' ] : _ ( 'Untitled' ));
767 $body = (( $content [ 'rss' ][ 'channel' ][ 'item' ][ 'description' ] != '' ) ? $content [ 'rss' ][ 'channel' ][ 'item' ][ 'description' ] : _ ( 'Undefined' ));
769 // clean content to prevent xss attack
771 $title = $purifier- > purify ( $title );
772 $body = $purifier- > purify ( $body );
773 $this- > store
-> updateContentAndTitle ( $item [ 'id' ], $title , $body , $this- > user
-> getId ());
774 Tools
:: logm ( 'Article ' . $item [ 'id' ] . ' updated.' );
777 Tools
:: logm ( 'Unvalid URL (' . $item [ 'url' ] . ') to fetch for article ' . $item [ 'id' ]);
784 'includeImport' => true ,
786 'recordsDownloadRequired' => $recordsDownloadRequired ,
787 'recordsUnderDownload' => IMPORT_LIMIT
,
788 'delay' => IMPORT_DELAY
* 1000
794 * export poche entries in json
795 * @return json all poche entries
797 public function export ()
799 $filename = "wallabag-export-" . $this- > user
-> getId (). "-" . date ( "Y-m-d" ). ".json" ;
800 header ( 'Content-Disposition: attachment; filename=' . $filename );
802 $entries = $this- > store
-> retrieveAll ( $this- > user
-> getId ());
803 echo $this- > tpl
-> render ( 'export.twig' , array (
804 'export' => Tools
:: renderJson ( $entries ),
806 Tools
:: logm ( 'export view' );
810 * Checks online the latest version of poche and cache it
811 * @param string $which 'prod' or 'dev'
812 * @return string latest $which version
814 private function _getPocheVersion ( $which = 'prod' ) {
815 $cache_file = CACHE
. '/' . $which ;
816 $check_time = time ();
818 # checks if the cached version file exists
819 if ( file_exists ( $cache_file ) && ( filemtime ( $cache_file ) > ( time () - 86400 ))) {
820 $version = file_get_contents ( $cache_file );
821 $check_time = filemtime ( $cache_file );
823 $version = file_get_contents ( 'http://static.wallabag.org/versions/' . $which );
824 file_put_contents ( $cache_file , $version , LOCK_EX
);
826 return array ( $version , $check_time );
830 * Update token for current user
832 public function updateToken ()
834 $token = Tools
:: generateToken ();
835 $this- > store
-> updateUserConfig ( $this- > user
-> getId (), 'token' , $token );
836 $currentConfig = $_SESSION [ 'poche_user' ]-> config
;
837 $currentConfig [ 'token' ] = $token ;
838 $_SESSION [ 'poche_user' ]-> setConfig ( $currentConfig );
843 * Generate RSS feeds for current user
847 * @param $tag_id if $type is 'tag', the id of the tag to generate feed for
848 * @param string $type the type of feed to generate
849 * @param int $limit the maximum number of items (0 means all)
851 public function generateFeeds ( $token , $user_id , $tag_id , $type = 'home' , $limit = 0 )
853 $allowed_types = array ( 'home' , 'fav' , 'archive' , 'tag' );
854 $config = $this- > store
-> getConfigUser ( $user_id );
856 if ( $config == null ) {
857 die ( sprintf ( _ ( 'User with this id (%d) does not exist.' ), $user_id ));
860 if (! in_array ( $type , $allowed_types ) || ! isset ( $config [ 'token' ]) || $token != $config [ 'token' ]) {
861 die ( _ ( 'Uh, there is a problem while generating feed. Wrong token used?' ));
864 $feed = new FeedWriter ( RSS2
);
865 $feed- > setTitle ( 'wallabag — ' . $type . ' feed' );
866 $feed- > setLink ( Tools
:: getPocheUrl ());
867 $feed- > setChannelElement ( 'pubDate' , date ( DATE_RSS
, time ()));
868 $feed- > setChannelElement ( 'generator' , 'wallabag' );
869 $feed- > setDescription ( 'wallabag ' . $type . ' elements' );
871 if ( $type == 'tag' ) {
872 $entries = $this- > store
-> retrieveEntriesByTag ( $tag_id , $user_id );
875 $entries = $this- > store
-> getEntriesByView ( $type , $user_id );
878 // if $limit is set to zero, use all entries
880 $limit = count ( $entries );
882 if ( count ( $entries ) > 0 ) {
883 for ( $i = 0 ; $i < min ( count ( $entries ), $limit ); $i ++
) {
884 $entry = $entries [ $i ];
885 $newItem = $feed- > createNewItem ();
886 $newItem- > setTitle ( $entry [ 'title' ]);
887 $newItem- > setSource ( Tools
:: getPocheUrl () . '?view=view&id=' . $entry [ 'id' ]);
888 $newItem- > setLink ( $entry [ 'url' ]);
889 $newItem- > setDate ( time ());
890 $newItem- > setDescription ( $entry [ 'content' ]);
891 $feed- > addItem ( $newItem );
895 $feed- > genarateFeed ();
902 * Returns new purifier object with actual config
904 private function _getPurifier ()
906 $config = HTMLPurifier_Config
:: createDefault ();
907 $config- > set ( 'Cache.SerializerPath' , CACHE
);
908 $config- > set ( 'HTML.SafeIframe' , true );
910 //allow YouTube, Vimeo and dailymotion videos
911 $config- > set ( 'URI.SafeIframeRegexp' , '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/|www\.dailymotion\.com/embed/video/)%' );
913 return new HTMLPurifier ( $config );