aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--inc/poche/Language.class.php3
-rwxr-xr-xinc/poche/Poche.class.php507
-rw-r--r--inc/poche/Routing.class.php13
-rw-r--r--inc/poche/Template.class.php3
-rwxr-xr-xinc/poche/Tools.class.php41
-rw-r--r--inc/poche/WallabagEpub.class.php137
-rwxr-xr-xinc/poche/global.inc.php1
-rw-r--r--inc/poche/pochePictures.php5
-rwxr-xr-xthemes/baggy/home.twig6
-rwxr-xr-xthemes/baggy/view.twig2
-rwxr-xr-xthemes/courgette/_view.twig2
-rwxr-xr-xthemes/courgette/home.twig6
-rwxr-xr-xthemes/default/home.twig6
-rwxr-xr-xthemes/default/view.twig2
14 files changed, 393 insertions, 341 deletions
diff --git a/inc/poche/Language.class.php b/inc/poche/Language.class.php
index 790cc197..8d3912f5 100644
--- a/inc/poche/Language.class.php
+++ b/inc/poche/Language.class.php
@@ -107,8 +107,7 @@ class Language
107 107
108 $_SESSION['poche_user']->setConfig($currentConfig); 108 $_SESSION['poche_user']->setConfig($currentConfig);
109 109
110 $this->wallabag->emptyCache(); 110 Tools::emptyCache();
111
112 Tools::redirect('?view=config'); 111 Tools::redirect('?view=config');
113 } 112 }
114} \ No newline at end of file 113} \ No newline at end of file
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php
index bc4320b8..a49413f2 100755
--- a/inc/poche/Poche.class.php
+++ b/inc/poche/Poche.class.php
@@ -74,61 +74,57 @@ class Poche
74 /** 74 /**
75 * Creates a new user 75 * Creates a new user
76 */ 76 */
77 public function createNewUser() 77 public function createNewUser($username, $password)
78 { 78 {
79 if (isset($_GET['newuser'])){ 79 if (!empty($username) && !empty($password)){
80 if ($_POST['newusername'] != "" && $_POST['password4newuser'] != ""){ 80 $newUsername = filter_var($username, FILTER_SANITIZE_STRING);
81 $newusername = filter_var($_POST['newusername'], FILTER_SANITIZE_STRING); 81 if (!$this->store->userExists($newUsername)){
82 if (!$this->store->userExists($newusername)){ 82 if ($this->store->install($newUsername, Tools::encodeString($password . $newUsername))) {
83 if ($this->store->install($newusername, Tools::encodeString($_POST['password4newuser'] . $newusername))) { 83 Tools::logm('The new user ' . $newUsername . ' has been installed');
84 Tools::logm('The new user '.$newusername.' has been installed'); 84 $this->messages->add('s', sprintf(_('The new user %s has been installed. Do you want to <a href="?logout">logout ?</a>'), $newUsername));
85 $this->messages->add('s', sprintf(_('The new user %s has been installed. Do you want to <a href="?logout">logout ?</a>'),$newusername)); 85 Tools::redirect();
86 Tools::redirect();
87 }
88 else {
89 Tools::logm('error during adding new user');
90 Tools::redirect();
91 }
92 } 86 }
93 else { 87 else {
94 $this->messages->add('e', sprintf(_('Error : An user with the name %s already exists !'),$newusername)); 88 Tools::logm('error during adding new user');
95 Tools::logm('An user with the name '.$newusername.' already exists !');
96 Tools::redirect(); 89 Tools::redirect();
97 } 90 }
98 } 91 }
92 else {
93 $this->messages->add('e', sprintf(_('Error : An user with the name %s already exists !'), $newUsername));
94 Tools::logm('An user with the name ' . $newUsername . ' already exists !');
95 Tools::redirect();
96 }
99 } 97 }
100 } 98 }
101 99
102 /** 100 /**
103 * Delete an existing user 101 * Delete an existing user
104 */ 102 */
105 public function deleteUser() 103 public function deleteUser($password)
106 { 104 {
107 if (isset($_GET['deluser'])){ 105 if ($this->store->listUsers() > 1) {
108 if ($this->store->listUsers() > 1) { 106 if (Tools::encodeString($password . $this->user->getUsername()) == $this->store->getUserPassword($this->user->getId())) {
109 if (Tools::encodeString($_POST['password4deletinguser'].$this->user->getUsername()) == $this->store->getUserPassword($this->user->getId())) { 107 $username = $this->user->getUsername();
110 $username = $this->user->getUsername(); 108 $this->store->deleteUserConfig($this->user->getId());
111 $this->store->deleteUserConfig($this->user->getId()); 109 Tools::logm('The configuration for user '. $username .' has been deleted !');
112 Tools::logm('The configuration for user '. $username .' has been deleted !'); 110 $this->store->deleteTagsEntriesAndEntries($this->user->getId());
113 $this->store->deleteTagsEntriesAndEntries($this->user->getId()); 111 Tools::logm('The entries for user '. $username .' has been deleted !');
114 Tools::logm('The entries for user '. $username .' has been deleted !'); 112 $this->store->deleteUser($this->user->getId());
115 $this->store->deleteUser($this->user->getId()); 113 Tools::logm('User '. $username .' has been completely deleted !');
116 Tools::logm('User '. $username .' has been completely deleted !'); 114 Session::logout();
117 Session::logout(); 115 Tools::logm('logout');
118 Tools::logm('logout'); 116 Tools::redirect();
119 Tools::redirect(); 117 $this->messages->add('s', sprintf(_('User %s has been successfully deleted !'), $username));
120 $this->messages->add('s', sprintf(_('User %s has been successfully deleted !'),$newusername));
121 }
122 else {
123 Tools::logm('Bad password !');
124 $this->messages->add('e', _('Error : The password is wrong !'));
125 }
126 } 118 }
127 else { 119 else {
128 Tools::logm('Only user !'); 120 Tools::logm('Bad password !');
129 $this->messages->add('e', _('Error : You are the only user, you cannot delete your account !')); 121 $this->messages->add('e', _('Error : The password is wrong !'));
130 } 122 }
131 } 123 }
124 else {
125 Tools::logm('Only user !');
126 $this->messages->add('e', _('Error : You are the only user, you cannot delete your account !'));
127 }
132 } 128 }
133 129
134 public function getDefaultConfig() 130 public function getDefaultConfig()
@@ -153,7 +149,7 @@ class Poche
153 $body = $content['rss']['channel']['item']['description']; 149 $body = $content['rss']['channel']['item']['description'];
154 150
155 // clean content from prevent xss attack 151 // clean content from prevent xss attack
156 $purifier = $this->getPurifier(); 152 $purifier = $this->_getPurifier();
157 $title = $purifier->purify($title); 153 $title = $purifier->purify($title);
158 $body = $purifier->purify($body); 154 $body = $purifier->purify($body);
159 155
@@ -318,10 +314,10 @@ class Poche
318 switch ($view) 314 switch ($view)
319 { 315 {
320 case 'config': 316 case 'config':
321 $dev_infos = $this->getPocheVersion('dev'); 317 $dev_infos = $this->_getPocheVersion('dev');
322 $dev = trim($dev_infos[0]); 318 $dev = trim($dev_infos[0]);
323 $check_time_dev = date('d-M-Y H:i', $dev_infos[1]); 319 $check_time_dev = date('d-M-Y H:i', $dev_infos[1]);
324 $prod_infos = $this->getPocheVersion('prod'); 320 $prod_infos = $this->_getPocheVersion('prod');
325 $prod = trim($prod_infos[0]); 321 $prod = trim($prod_infos[0]);
326 $check_time_prod = date('d-M-Y H:i', $prod_infos[1]); 322 $check_time_prod = date('d-M-Y H:i', $prod_infos[1]);
327 $compare_dev = version_compare(POCHE, $dev); 323 $compare_dev = version_compare(POCHE, $dev);
@@ -461,7 +457,7 @@ class Poche
461 * @todo set the new password in function header like this updatePassword($newPassword) 457 * @todo set the new password in function header like this updatePassword($newPassword)
462 * @return boolean 458 * @return boolean
463 */ 459 */
464 public function updatePassword() 460 public function updatePassword($password, $confirmPassword)
465 { 461 {
466 if (MODE_DEMO) { 462 if (MODE_DEMO) {
467 $this->messages->add('i', _('in demo mode, you can\'t update your password')); 463 $this->messages->add('i', _('in demo mode, you can\'t update your password'));
@@ -469,10 +465,10 @@ class Poche
469 Tools::redirect('?view=config'); 465 Tools::redirect('?view=config');
470 } 466 }
471 else { 467 else {
472 if (isset($_POST['password']) && isset($_POST['password_repeat'])) { 468 if (isset($password) && isset($confirmPassword)) {
473 if ($_POST['password'] == $_POST['password_repeat'] && $_POST['password'] != "") { 469 if ($password == $confirmPassword && !empty($password)) {
474 $this->messages->add('s', _('your password has been updated')); 470 $this->messages->add('s', _('your password has been updated'));
475 $this->store->updatePassword($this->user->getId(), Tools::encodeString($_POST['password'] . $this->user->getUsername())); 471 $this->store->updatePassword($this->user->getId(), Tools::encodeString($password . $this->user->getUsername()));
476 Session::logout(); 472 Session::logout();
477 Tools::logm('password updated'); 473 Tools::logm('password updated');
478 Tools::redirect(); 474 Tools::redirect();
@@ -486,22 +482,24 @@ class Poche
486 } 482 }
487 483
488 /** 484 /**
489 * get credentials from differents sources 485 * Get credentials from differents sources
490 * it redirects the user to the $referer link 486 * It redirects the user to the $referer link
487 *
491 * @return array 488 * @return array
492 */ 489 */
493 private function credentials() { 490 private function credentials()
494 if(isset($_SERVER['PHP_AUTH_USER'])) { 491 {
495 return array($_SERVER['PHP_AUTH_USER'],'php_auth',true); 492 if (isset($_SERVER['PHP_AUTH_USER'])) {
493 return array($_SERVER['PHP_AUTH_USER'], 'php_auth', true);
496 } 494 }
497 if(!empty($_POST['login']) && !empty($_POST['password'])) { 495 if (!empty($_POST['login']) && !empty($_POST['password'])) {
498 return array($_POST['login'],$_POST['password'],false); 496 return array($_POST['login'], $_POST['password'], false);
499 } 497 }
500 if(isset($_SERVER['REMOTE_USER'])) { 498 if (isset($_SERVER['REMOTE_USER'])) {
501 return array($_SERVER['REMOTE_USER'],'http_auth',true); 499 return array($_SERVER['REMOTE_USER'], 'http_auth', true);
502 } 500 }
503 501
504 return array(false,false,false); 502 return array(false, false, false);
505 } 503 }
506 504
507 /** 505 /**
@@ -550,129 +548,148 @@ class Poche
550 } 548 }
551 549
552 /** 550 /**
553 * import datas into your poche 551 * import datas into your wallabag
554 * @return boolean 552 * @return boolean
555 */ 553 */
556 public function import() { 554 public function import()
557 555 {
558 if ( isset($_FILES['file']) ) { 556 if (isset($_FILES['file'])) {
559 Tools::logm('Import stated: parsing file'); 557 Tools::logm('Import stated: parsing file');
560 558
561 // assume, that file is in json format 559 // assume, that file is in json format
562 $str_data = file_get_contents($_FILES['file']['tmp_name']); 560
563 $data = json_decode($str_data, true); 561 $str_data = file_get_contents($_FILES['file']['tmp_name']);
564 562 $data = json_decode($str_data, true);
565 if ( $data === null ) { 563 if ($data === null) {
566 //not json - assume html 564
567 $html = new simple_html_dom(); 565 // not json - assume html
568 $html->load_file($_FILES['file']['tmp_name']); 566
569 $data = array(); 567 $html = new simple_html_dom();
570 $read = 0; 568 $html->load_file($_FILES['file']['tmp_name']);
571 foreach (array('ol','ul') as $list) { 569 $data = array();
572 foreach ($html->find($list) as $ul) { 570 $read = 0;
573 foreach ($ul->find('li') as $li) { 571 foreach(array('ol','ul') as $list) {
574 $tmpEntry = array(); 572 foreach($html->find($list) as $ul) {
575 $a = $li->find('a'); 573 foreach($ul->find('li') as $li) {
576 $tmpEntry['url'] = $a[0]->href; 574 $tmpEntry = array();
577 $tmpEntry['tags'] = $a[0]->tags; 575 $a = $li->find('a');
578 $tmpEntry['is_read'] = $read; 576 $tmpEntry['url'] = $a[0]->href;
579 if ($tmpEntry['url']) { 577 $tmpEntry['tags'] = $a[0]->tags;
580 $data[] = $tmpEntry; 578 $tmpEntry['is_read'] = $read;
581 } 579 if ($tmpEntry['url']) {
582 } 580 $data[] = $tmpEntry;
583 # the second <ol/ul> is for read links 581 }
584 $read = ((sizeof($data) && $read)?0:1); 582 }
583
584 // the second <ol/ul> is for read links
585
586 $read = ((sizeof($data) && $read) ? 0 : 1);
587 }
588 }
585 } 589 }
586 }
587 }
588 590
589 //for readability structure 591 // for readability structure
590 foreach ($data as $record) { 592
591 if (is_array($record)) { 593 foreach($data as $record) {
592 $data[] = $record; 594 if (is_array($record)) {
593 foreach ($record as $record2) { 595 $data[] = $record;
594 if (is_array($record2)) { 596 foreach($record as $record2) {
595 $data[] = $record2; 597 if (is_array($record2)) {
596 } 598 $data[] = $record2;
599 }
600 }
601 }
597 } 602 }
598 }
599 }
600 603
601 $urlsInserted = array(); //urls of articles inserted 604 $urlsInserted = array(); //urls of articles inserted
602 foreach ($data as $record) { 605 foreach($data as $record) {
603 $url = trim( isset($record['article__url']) ? $record['article__url'] : (isset($record['url']) ? $record['url'] : '') ); 606 $url = trim(isset($record['article__url']) ? $record['article__url'] : (isset($record['url']) ? $record['url'] : ''));
604 if ( $url and !in_array($url, $urlsInserted) ) { 607 if ($url and !in_array($url, $urlsInserted)) {
605 $title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ').'</a> <a href="./?import">'._('click to finish import').'</a><a>'); 608 $title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ') . '</a> <a href="./?import">' . _('click to finish import') . '</a><a>');
606 $body = (isset($record['content']) ? $record['content'] : ''); 609 $body = (isset($record['content']) ? $record['content'] : '');
607 $isRead = (isset($record['is_read']) ? intval($record['is_read']) : (isset($record['archive'])?intval($record['archive']):0)); 610 $isRead = (isset($record['is_read']) ? intval($record['is_read']) : (isset($record['archive']) ? intval($record['archive']) : 0));
608 $isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : (isset($record['favorite'])?intval($record['favorite']):0) ); 611 $isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : (isset($record['favorite']) ? intval($record['favorite']) : 0));
609 //insert new record 612
610 $id = $this->store->add($url, $title, $body, $this->user->getId(), $isFavorite, $isRead); 613 // insert new record
611 if ( $id ) { 614
612 $urlsInserted[] = $url; //add 615 $id = $this->store->add($url, $title, $body, $this->user->getId() , $isFavorite, $isRead);
613 616 if ($id) {
614 if ( isset($record['tags']) && trim($record['tags']) ) { 617 $urlsInserted[] = $url; //add
615 //@TODO: set tags 618 if (isset($record['tags']) && trim($record['tags'])) {
616 619
617 } 620 // @TODO: set tags
621
622 }
623 }
624 }
618 } 625 }
619 }
620 }
621 626
622 $i = sizeof($urlsInserted); 627 $i = sizeof($urlsInserted);
623 if ( $i > 0 ) { 628 if ($i > 0) {
624 $this->messages->add('s', _('Articles inserted: ').$i._('. Please note, that some may be marked as "read".')); 629 $this->messages->add('s', _('Articles inserted: ') . $i . _('. Please note, that some may be marked as "read".'));
630 }
631
632 Tools::logm('Import of articles finished: ' . $i . ' articles added (w/o content if not provided).');
625 } 633 }
626 Tools::logm('Import of articles finished: '.$i.' articles added (w/o content if not provided).');
627 }
628 //file parsing finished here
629 634
630 //now download article contents if any 635 // file parsing finished here
636 // now download article contents if any
637 // check if we need to download any content
631 638
632 //check if we need to download any content 639 $recordsDownloadRequired = $this->store->retrieveUnfetchedEntriesCount($this->user->getId());
633 $recordsDownloadRequired = $this->store->retrieveUnfetchedEntriesCount($this->user->getId()); 640
634 if ( $recordsDownloadRequired == 0 ) { 641 if ($recordsDownloadRequired == 0) {
635 //nothing to download
636 $this->messages->add('s', _('Import finished.'));
637 Tools::logm('Import finished completely');
638 Tools::redirect();
639 }
640 else {
641 //if just inserted - don't download anything, download will start in next reload
642 if ( !isset($_FILES['file']) ) {
643 //download next batch
644 Tools::logm('Fetching next batch of articles...');
645 $items = $this->store->retrieveUnfetchedEntries($this->user->getId(), IMPORT_LIMIT);
646 642
647 $purifier = $this->getPurifier(); 643 // nothing to download
648 644
649 foreach ($items as $item) { 645 $this->messages->add('s', _('Import finished.'));
650 $url = new Url(base64_encode($item['url'])); 646 Tools::logm('Import finished completely');
651 Tools::logm('Fetching article '.$item['id']); 647 Tools::redirect();
652 $content = Tools::getPageContent($url); 648 }
649 else {
653 650
654 $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled')); 651 // if just inserted - don't download anything, download will start in next reload
655 $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
656 652
657 //clean content to prevent xss attack 653 if (!isset($_FILES['file'])) {
658 $title = $purifier->purify($title);
659 $body = $purifier->purify($body);
660 654
661 $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId()); 655 // download next batch
662 Tools::logm('Article '.$item['id'].' updated.');
663 }
664 656
657 Tools::logm('Fetching next batch of articles...');
658 $items = $this->store->retrieveUnfetchedEntries($this->user->getId() , IMPORT_LIMIT);
659 $purifier = $this->_getPurifier();
660 foreach($items as $item) {
661 $url = new Url(base64_encode($item['url']));
662 Tools::logm('Fetching article ' . $item['id']);
663 $content = Tools::getPageContent($url);
664 $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
665 $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
666
667 // clean content to prevent xss attack
668
669 $title = $purifier->purify($title);
670 $body = $purifier->purify($body);
671 $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
672 Tools::logm('Article ' . $item['id'] . ' updated.');
673 }
674 }
665 } 675 }
666 }
667 676
668 return array('includeImport'=>true, 'import'=>array('recordsDownloadRequired'=>$recordsDownloadRequired, 'recordsUnderDownload'=> IMPORT_LIMIT, 'delay'=> IMPORT_DELAY * 1000) ); 677 return array(
678 'includeImport' => true,
679 'import' => array(
680 'recordsDownloadRequired' => $recordsDownloadRequired,
681 'recordsUnderDownload' => IMPORT_LIMIT,
682 'delay' => IMPORT_DELAY * 1000
683 )
684 );
669 } 685 }
670 686
671 /** 687 /**
672 * export poche entries in json 688 * export poche entries in json
673 * @return json all poche entries 689 * @return json all poche entries
674 */ 690 */
675 public function export() { 691 public function export()
692 {
676 $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json"; 693 $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
677 header('Content-Disposition: attachment; filename='.$filename); 694 header('Content-Disposition: attachment; filename='.$filename);
678 695
@@ -688,7 +705,7 @@ class Poche
688 * @param string $which 'prod' or 'dev' 705 * @param string $which 'prod' or 'dev'
689 * @return string latest $which version 706 * @return string latest $which version
690 */ 707 */
691 private function getPocheVersion($which = 'prod') { 708 private function _getPocheVersion($which = 'prod') {
692 $cache_file = CACHE . '/' . $which; 709 $cache_file = CACHE . '/' . $which;
693 $check_time = time(); 710 $check_time = time();
694 711
@@ -703,29 +720,27 @@ class Poche
703 return array($version, $check_time); 720 return array($version, $check_time);
704 } 721 }
705 722
706 public function generateToken() 723 /**
724 * Update token for current user
725 */
726 public function updateToken()
707 { 727 {
708 if (ini_get('open_basedir') === '') { 728 $token = Tools::generateToken();
709 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 729 $this->store->updateUserConfig($this->user->getId(), 'token', $token);
710 echo 'This is a server using Windows!'; 730 $currentConfig = $_SESSION['poche_user']->config;
711 // alternative to /dev/urandom for Windows 731 $currentConfig['token'] = $token;
712 $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20); 732 $_SESSION['poche_user']->setConfig($currentConfig);
713 } else { 733 Tools::redirect();
714 $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
715 }
716 }
717 else {
718 $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
719 }
720
721 $token = str_replace('+', '', $token);
722 $this->store->updateUserConfig($this->user->getId(), 'token', $token);
723 $currentConfig = $_SESSION['poche_user']->config;
724 $currentConfig['token'] = $token;
725 $_SESSION['poche_user']->setConfig($currentConfig);
726 Tools::redirect();
727 } 734 }
728 735
736 /**
737 * Generate RSS feeds for current user
738 *
739 * @param $token
740 * @param $user_id
741 * @param $tag_id
742 * @param string $type
743 */
729 public function generateFeeds($token, $user_id, $tag_id, $type = 'home') 744 public function generateFeeds($token, $user_id, $tag_id, $type = 'home')
730 { 745 {
731 $allowed_types = array('home', 'fav', 'archive', 'tag'); 746 $allowed_types = array('home', 'fav', 'archive', 'tag');
@@ -738,7 +753,6 @@ class Poche
738 if (!in_array($type, $allowed_types) || $token != $config['token']) { 753 if (!in_array($type, $allowed_types) || $token != $config['token']) {
739 die(_('Uh, there is a problem while generating feeds.')); 754 die(_('Uh, there is a problem while generating feeds.'));
740 } 755 }
741 // Check the token
742 756
743 $feed = new FeedWriter(RSS2); 757 $feed = new FeedWriter(RSS2);
744 $feed->setTitle('wallabag — ' . $type . ' feed'); 758 $feed->setTitle('wallabag — ' . $type . ' feed');
@@ -770,147 +784,22 @@ class Poche
770 exit; 784 exit;
771 } 785 }
772 786
773 public function emptyCache() {
774 $files = new RecursiveIteratorIterator(
775 new RecursiveDirectoryIterator(CACHE, RecursiveDirectoryIterator::SKIP_DOTS),
776 RecursiveIteratorIterator::CHILD_FIRST
777 );
778
779 foreach ($files as $fileinfo) {
780 $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
781 $todo($fileinfo->getRealPath());
782 }
783 787
784 Tools::logm('empty cache');
785 $this->messages->add('s', _('Cache deleted.'));
786 Tools::redirect();
787 }
788 788
789 /** 789 /**
790 * return new purifier object with actual config 790 * Returns new purifier object with actual config
791 */ 791 */
792 protected function getPurifier() { 792 private function _getPurifier()
793 $config = HTMLPurifier_Config::createDefault(); 793 {
794 $config->set('Cache.SerializerPath', CACHE); 794 $config = HTMLPurifier_Config::createDefault();
795 $config->set('HTML.SafeIframe', true); 795 $config->set('Cache.SerializerPath', CACHE);
796 $config->set('HTML.SafeIframe', true);
796 797
797 //allow YouTube, Vimeo and dailymotion videos 798 //allow YouTube, Vimeo and dailymotion videos
798 $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/|www\.dailymotion\.com/embed/video/)%'); 799 $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/|www\.dailymotion\.com/embed/video/)%');
799 800
800 return new HTMLPurifier($config); 801 return new HTMLPurifier($config);
801 } 802 }
802 803
803 /**
804 * handle epub
805 */
806 public function createEpub() {
807
808 switch ($_GET['method']) {
809 case 'id':
810 $entryID = filter_var($_GET['id'],FILTER_SANITIZE_NUMBER_INT);
811 $entry = $this->store->retrieveOneById($entryID, $this->user->getId());
812 $entries = array($entry);
813 $bookTitle = $entry['title'];
814 $bookFileName = substr($bookTitle, 0, 200);
815 break;
816 case 'all':
817 $entries = $this->store->retrieveAll($this->user->getId());
818 $bookTitle = sprintf(_('All my articles on '), date(_('d.m.y'))); #translatable because each country has it's own date format system
819 $bookFileName = _('Allarticles') . date(_('dmY'));
820 break;
821 case 'tag':
822 $tag = filter_var($_GET['tag'],FILTER_SANITIZE_STRING);
823 $tags_id = $this->store->retrieveAllTags($this->user->getId(),$tag);
824 $tag_id = $tags_id[0]["id"]; // we take the first result, which is supposed to match perfectly. There must be a workaround.
825 $entries = $this->store->retrieveEntriesByTag($tag_id,$this->user->getId());
826 $bookTitle = sprintf(_('Articles tagged %s'),$tag);
827 $bookFileName = substr(sprintf(_('Tag %s'),$tag), 0, 200);
828 break;
829 case 'category':
830 $category = filter_var($_GET['category'],FILTER_SANITIZE_STRING);
831 $entries = $this->store->getEntriesByView($category,$this->user->getId());
832 $bookTitle = sprintf(_('All articles in category %s'), $category);
833 $bookFileName = substr(sprintf(_('Category %s'),$category), 0, 200);
834 break;
835 case 'search':
836 $search = filter_var($_GET['search'],FILTER_SANITIZE_STRING);
837 $entries = $this->store->search($search,$this->user->getId());
838 $bookTitle = sprintf(_('All articles for search %s'), $search);
839 $bookFileName = substr(sprintf(_('Search %s'), $search), 0, 200);
840 break;
841 case 'default':
842 die(_('Uh, there is a problem while generating epub.'));
843
844 }
845
846 $content_start =
847 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
848 . "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n"
849 . "<head>"
850 . "<meta http-equiv=\"Default-Style\" content=\"text/html; charset=utf-8\" />\n"
851 . "<title>wallabag articles book</title>\n"
852 . "</head>\n"
853 . "<body>\n";
854
855 $bookEnd = "</body>\n</html>\n";
856
857 $log = new Logger("wallabag", TRUE);
858 $fileDir = CACHE;
859
860 $book = new EPub(EPub::BOOK_VERSION_EPUB3, DEBUG_POCHE);
861 $log->logLine("new EPub()");
862 $log->logLine("EPub class version: " . EPub::VERSION);
863 $log->logLine("EPub Req. Zip version: " . EPub::REQ_ZIP_VERSION);
864 $log->logLine("Zip version: " . Zip::VERSION);
865 $log->logLine("getCurrentServerURL: " . $book->getCurrentServerURL());
866 $log->logLine("getCurrentPageURL..: " . $book->getCurrentPageURL());
867
868 $book->setTitle(_('wallabag\'s articles'));
869 $book->setIdentifier("http://$_SERVER[HTTP_HOST]", EPub::IDENTIFIER_URI); // Could also be the ISBN number, prefered for published books, or a UUID.
870 //$book->setLanguage("en"); // Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc.
871 $book->setDescription(_("Some articles saved on my wallabag"));
872 $book->setAuthor("wallabag","wallabag");
873 $book->setPublisher("wallabag","wallabag"); // I hope this is a non existant address :)
874 $book->setDate(time()); // Strictly not needed as the book date defaults to time().
875 //$book->setRights("Copyright and licence information specific for the book."); // As this is generated, this _could_ contain the name or licence information of the user who purchased the book, if needed. If this is used that way, the identifier must also be made unique for the book.
876 $book->setSourceURL("http://$_SERVER[HTTP_HOST]");
877
878 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, "PHP");
879 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, "wallabag");
880
881 $cssData = "body {\n margin-left: .5em;\n margin-right: .5em;\n text-align: justify;\n}\n\np {\n font-family: serif;\n font-size: 10pt;\n text-align: justify;\n text-indent: 1em;\n margin-top: 0px;\n margin-bottom: 1ex;\n}\n\nh1, h2 {\n font-family: sans-serif;\n font-style: italic;\n text-align: center;\n background-color: #6b879c;\n color: white;\n width: 100%;\n}\n\nh1 {\n margin-bottom: 2px;\n}\n\nh2 {\n margin-top: -2px;\n margin-bottom: 2px;\n}\n";
882
883 $log->logLine("Add Cover");
884 804
885 $fullTitle = "<h1> " . $bookTitle . "</h1>\n";
886
887 $book->setCoverImage("Cover.png", file_get_contents("themes/baggy/img/apple-touch-icon-152.png"), "image/png", $fullTitle);
888
889 $cover = $content_start . '<div style="text-align:center;"><p>' . _('Produced by wallabag with PHPePub') . '</p><p>'. _('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.') . '</p></div>' . $bookEnd;
890
891 //$book->addChapter("Table of Contents", "TOC.xhtml", NULL, false, EPub::EXTERNAL_REF_IGNORE);
892 $book->addChapter("Notices", "Cover2.html", $cover);
893
894 $book->buildTOC();
895
896 foreach ($entries as $entry) { //set tags as subjects
897 $tags = $this->store->retrieveTagsByEntry($entry['id']);
898 foreach ($tags as $tag) {
899 $book->setSubject($tag['value']);
900 }
901
902 $log->logLine("Set up parameters");
903
904 $chapter = $content_start . $entry['content'] . $bookEnd;
905 $book->addChapter($entry['title'], htmlspecialchars($entry['title']) . ".html", $chapter, true, EPub::EXTERNAL_REF_ADD);
906 $log->logLine("Added chapter " . $entry['title']);
907 }
908
909 if (DEBUG_POCHE) {
910 $epuplog = $book->getLog();
911 $book->addChapter("Log", "Log.html", $content_start . $log->getLog() . "\n</pre>" . $bookEnd); // log generation
912 }
913 $book->finalize();
914 $zipData = $book->sendBook($bookFileName);
915 }
916} 805}
diff --git a/inc/poche/Routing.class.php b/inc/poche/Routing.class.php
index 8c2f38e3..eb4c4d90 100644
--- a/inc/poche/Routing.class.php
+++ b/inc/poche/Routing.class.php
@@ -105,20 +105,21 @@ class Routing
105 $this->wallabag->logout(); 105 $this->wallabag->logout();
106 } elseif (isset($_GET['config'])) { 106 } elseif (isset($_GET['config'])) {
107 // update password 107 // update password
108 $this->wallabag->updatePassword(); 108 $this->wallabag->updatePassword($_POST['password'], $_POST['password_repeat']);
109 } elseif (isset($_GET['newuser'])) { 109 } elseif (isset($_GET['newuser'])) {
110 $this->wallabag->createNewUser(); 110 $this->wallabag->createNewUser($_POST['newusername'], $_POST['password4newuser']);
111 } elseif (isset($_GET['deluser'])) { 111 } elseif (isset($_GET['deluser'])) {
112 $this->wallabag->deleteUser(); 112 $this->wallabag->deleteUser($_POST['password4deletinguser']);
113 } elseif (isset($_GET['epub'])) { 113 } elseif (isset($_GET['epub'])) {
114 $this->wallabag->createEpub(); 114 $epub = new WallabagEpub($this->wallabag, $_GET['method'], $_GET['id'], $_GET['value']);
115 $epub->run();
115 } elseif (isset($_GET['import'])) { 116 } elseif (isset($_GET['import'])) {
116 $import = $this->wallabag->import(); 117 $import = $this->wallabag->import();
117 $tplVars = array_merge($this->vars, $import); 118 $tplVars = array_merge($this->vars, $import);
118 } elseif (isset($_GET['download'])) { 119 } elseif (isset($_GET['download'])) {
119 Tools::downloadDb(); 120 Tools::downloadDb();
120 } elseif (isset($_GET['empty-cache'])) { 121 } elseif (isset($_GET['empty-cache'])) {
121 $this->wallabag->emptyCache(); 122 Tools::emptyCache();
122 } elseif (isset($_GET['export'])) { 123 } elseif (isset($_GET['export'])) {
123 $this->wallabag->export(); 124 $this->wallabag->export();
124 } elseif (isset($_GET['updatetheme'])) { 125 } elseif (isset($_GET['updatetheme'])) {
@@ -129,7 +130,7 @@ class Routing
129 $this->wallabag->uploadFile(); 130 $this->wallabag->uploadFile();
130 } elseif (isset($_GET['feed'])) { 131 } elseif (isset($_GET['feed'])) {
131 if (isset($_GET['action']) && $_GET['action'] == 'generate') { 132 if (isset($_GET['action']) && $_GET['action'] == 'generate') {
132 $this->wallabag->generateToken(); 133 $this->wallabag->updateToken();
133 } 134 }
134 else { 135 else {
135 $tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0); 136 $tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0);
diff --git a/inc/poche/Template.class.php b/inc/poche/Template.class.php
index 0e09ad64..b686f2ec 100644
--- a/inc/poche/Template.class.php
+++ b/inc/poche/Template.class.php
@@ -229,8 +229,7 @@ class Template extends Twig_Environment
229 229
230 $_SESSION['poche_user']->setConfig($currentConfig); 230 $_SESSION['poche_user']->setConfig($currentConfig);
231 231
232 $this->wallabag->emptyCache(); 232 Tools::emptyCache();
233
234 Tools::redirect('?view=config'); 233 Tools::redirect('?view=config');
235 } 234 }
236} \ No newline at end of file 235} \ No newline at end of file
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php
index 762e4446..63137d76 100755
--- a/inc/poche/Tools.class.php
+++ b/inc/poche/Tools.class.php
@@ -10,11 +10,6 @@
10 10
11final class Tools 11final class Tools
12{ 12{
13 private function __construct()
14 {
15
16 }
17
18 /** 13 /**
19 * Initialize PHP environment 14 * Initialize PHP environment
20 */ 15 */
@@ -393,4 +388,40 @@ final class Tools
393 return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest'; 388 return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
394 } 389 }
395 390
391 /*
392 * Empty cache folder
393 */
394 public static function emptyCache()
395 {
396 $files = new RecursiveIteratorIterator(
397 new RecursiveDirectoryIterator(CACHE, RecursiveDirectoryIterator::SKIP_DOTS),
398 RecursiveIteratorIterator::CHILD_FIRST
399 );
400
401 foreach ($files as $fileInfo) {
402 $todo = ($fileInfo->isDir() ? 'rmdir' : 'unlink');
403 $todo($fileInfo->getRealPath());
404 }
405
406 Tools::logm('empty cache');
407 Tools::redirect();
408 }
409
410 public static function generateToken()
411 {
412 if (ini_get('open_basedir') === '') {
413 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
414 // alternative to /dev/urandom for Windows
415 $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
416 } else {
417 $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
418 }
419 }
420 else {
421 $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
422 }
423
424 return str_replace('+', '', $token);
425 }
426
396} 427}
diff --git a/inc/poche/WallabagEpub.class.php b/inc/poche/WallabagEpub.class.php
new file mode 100644
index 00000000..b81d9bfd
--- /dev/null
+++ b/inc/poche/WallabagEpub.class.php
@@ -0,0 +1,137 @@
1<?php
2/**
3 * wallabag, self hostable application allowing you to not miss any content anymore
4 *
5 * @category wallabag
6 * @author Nicolas LÅ“uillet <nicolas@loeuillet.org>
7 * @copyright 2013
8 * @license http://opensource.org/licenses/MIT see COPYING file
9 */
10
11class WallabagEpub
12{
13 protected $wallabag;
14 protected $method;
15 protected $id;
16 protected $value;
17
18 public function __construct(Poche $wallabag, $method, $id, $value)
19 {
20 $this->wallabag = $wallabag;
21 $this->method = $method;
22 $this->id = $id;
23 $this->value = $value;
24 }
25
26 /**
27 * handle ePub
28 */
29 public function run()
30 {
31 switch ($this->method) {
32 case 'id':
33 $entryID = filter_var($this->id, FILTER_SANITIZE_NUMBER_INT);
34 $entry = $this->wallabag->store->retrieveOneById($entryID, $this->wallabag->user->getId());
35 $entries = array($entry);
36 $bookTitle = $entry['title'];
37 $bookFileName = substr($bookTitle, 0, 200);
38 break;
39 case 'all':
40 $entries = $this->wallabag->store->retrieveAll($this->wallabag->user->getId());
41 $bookTitle = sprintf(_('All my articles on '), date(_('d.m.y'))); #translatable because each country has it's own date format system
42 $bookFileName = _('Allarticles') . date(_('dmY'));
43 break;
44 case 'tag':
45 $tag = filter_var($this->value, FILTER_SANITIZE_STRING);
46 $tags_id = $this->wallabag->store->retrieveAllTags($this->wallabag->user->getId(), $tag);
47 $tag_id = $tags_id[0]["id"]; // we take the first result, which is supposed to match perfectly. There must be a workaround.
48 $entries = $this->wallabag->store->retrieveEntriesByTag($tag_id, $this->wallabag->user->getId());
49 $bookTitle = sprintf(_('Articles tagged %s'), $tag);
50 $bookFileName = substr(sprintf(_('Tag %s'), $tag), 0, 200);
51 break;
52 case 'category':
53 $category = filter_var($this->value, FILTER_SANITIZE_STRING);
54 $entries = $this->wallabag->store->getEntriesByView($category, $this->wallabag->user->getId());
55 $bookTitle = sprintf(_('All articles in category %s'), $category);
56 $bookFileName = substr(sprintf(_('Category %s'), $category), 0, 200);
57 break;
58 case 'search':
59 $search = filter_var($this->value, FILTER_SANITIZE_STRING);
60 $entries = $this->store->search($search, $this->wallabag->user->getId());
61 $bookTitle = sprintf(_('All articles for search %s'), $search);
62 $bookFileName = substr(sprintf(_('Search %s'), $search), 0, 200);
63 break;
64 case 'default':
65 die(_('Uh, there is a problem while generating epub.'));
66 }
67
68 $content_start =
69 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
70 . "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n"
71 . "<head>"
72 . "<meta http-equiv=\"Default-Style\" content=\"text/html; charset=utf-8\" />\n"
73 . "<title>wallabag articles book</title>\n"
74 . "</head>\n"
75 . "<body>\n";
76
77 $bookEnd = "</body>\n</html>\n";
78
79 $log = new Logger("wallabag", TRUE);
80 $fileDir = CACHE;
81
82 $book = new EPub(EPub::BOOK_VERSION_EPUB3, DEBUG_POCHE);
83 $log->logLine("new EPub()");
84 $log->logLine("EPub class version: " . EPub::VERSION);
85 $log->logLine("EPub Req. Zip version: " . EPub::REQ_ZIP_VERSION);
86 $log->logLine("Zip version: " . Zip::VERSION);
87 $log->logLine("getCurrentServerURL: " . $book->getCurrentServerURL());
88 $log->logLine("getCurrentPageURL..: " . $book->getCurrentPageURL());
89
90 $book->setTitle(_('wallabag\'s articles'));
91 $book->setIdentifier("http://$_SERVER[HTTP_HOST]", EPub::IDENTIFIER_URI); // Could also be the ISBN number, prefered for published books, or a UUID.
92 //$book->setLanguage("en"); // Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc.
93 $book->setDescription(_("Some articles saved on my wallabag"));
94 $book->setAuthor("wallabag", "wallabag");
95 $book->setPublisher("wallabag", "wallabag"); // I hope this is a non existant address :)
96 $book->setDate(time()); // Strictly not needed as the book date defaults to time().
97 //$book->setRights("Copyright and licence information specific for the book."); // As this is generated, this _could_ contain the name or licence information of the user who purchased the book, if needed. If this is used that way, the identifier must also be made unique for the book.
98 $book->setSourceURL("http://$_SERVER[HTTP_HOST]");
99
100 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, "PHP");
101 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, "wallabag");
102
103 $cssData = "body {\n margin-left: .5em;\n margin-right: .5em;\n text-align: justify;\n}\n\np {\n font-family: serif;\n font-size: 10pt;\n text-align: justify;\n text-indent: 1em;\n margin-top: 0px;\n margin-bottom: 1ex;\n}\n\nh1, h2 {\n font-family: sans-serif;\n font-style: italic;\n text-align: center;\n background-color: #6b879c;\n color: white;\n width: 100%;\n}\n\nh1 {\n margin-bottom: 2px;\n}\n\nh2 {\n margin-top: -2px;\n margin-bottom: 2px;\n}\n";
104
105 $log->logLine("Add Cover");
106
107 $fullTitle = "<h1> " . $bookTitle . "</h1>\n";
108
109 $book->setCoverImage("Cover.png", file_get_contents("themes/baggy/img/apple-touch-icon-152.png"), "image/png", $fullTitle);
110
111 $cover = $content_start . '<div style="text-align:center;"><p>' . _('Produced by wallabag with PHPePub') . '</p><p>'. _('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.') . '</p></div>' . $bookEnd;
112
113 //$book->addChapter("Table of Contents", "TOC.xhtml", NULL, false, EPub::EXTERNAL_REF_IGNORE);
114 $book->addChapter("Notices", "Cover2.html", $cover);
115
116 $book->buildTOC();
117
118 foreach ($entries as $entry) { //set tags as subjects
119 $tags = $this->wallabag->store->retrieveTagsByEntry($entry['id']);
120 foreach ($tags as $tag) {
121 $book->setSubject($tag['value']);
122 }
123
124 $log->logLine("Set up parameters");
125
126 $chapter = $content_start . $entry['content'] . $bookEnd;
127 $book->addChapter($entry['title'], htmlspecialchars($entry['title']) . ".html", $chapter, true, EPub::EXTERNAL_REF_ADD);
128 $log->logLine("Added chapter " . $entry['title']);
129 }
130
131 if (DEBUG_POCHE) {
132 $book->addChapter("Log", "Log.html", $content_start . $log->getLog() . "\n</pre>" . $bookEnd); // log generation
133 }
134 $book->finalize();
135 $zipData = $book->sendBook($bookFileName);
136 }
137} \ No newline at end of file
diff --git a/inc/poche/global.inc.php b/inc/poche/global.inc.php
index 3eb64df0..b8c487e3 100755
--- a/inc/poche/global.inc.php
+++ b/inc/poche/global.inc.php
@@ -22,6 +22,7 @@ require_once ROOT . '/vendor/autoload.php';
22require_once INCLUDES . '/poche/Template.class.php'; 22require_once INCLUDES . '/poche/Template.class.php';
23require_once INCLUDES . '/poche/Language.class.php'; 23require_once INCLUDES . '/poche/Language.class.php';
24require_once INCLUDES . '/poche/Routing.class.php'; 24require_once INCLUDES . '/poche/Routing.class.php';
25require_once INCLUDES . '/poche/WallabagEpub.class.php';
25require_once INCLUDES . '/poche/Poche.class.php'; 26require_once INCLUDES . '/poche/Poche.class.php';
26 27
27require_once INCLUDES . '/poche/Database.class.php'; 28require_once INCLUDES . '/poche/Database.class.php';
diff --git a/inc/poche/pochePictures.php b/inc/poche/pochePictures.php
index 26bf0706..7a914f90 100644
--- a/inc/poche/pochePictures.php
+++ b/inc/poche/pochePictures.php
@@ -11,11 +11,6 @@
11 11
12final class Picture 12final class Picture
13{ 13{
14 private function __construct()
15 {
16
17 }
18
19 /** 14 /**
20 * Changing pictures URL in article content 15 * Changing pictures URL in article content
21 */ 16 */
diff --git a/themes/baggy/home.twig b/themes/baggy/home.twig
index 3942d3bf..e788b588 100755
--- a/themes/baggy/home.twig
+++ b/themes/baggy/home.twig
@@ -61,9 +61,9 @@
61 61
62 {% if search_term is defined %}<a title="{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}" href="./?action=add_tag&search={{ search_term }}">{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}</a>{% endif %} 62 {% if search_term is defined %}<a title="{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}" href="./?action=add_tag&search={{ search_term }}">{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}</a>{% endif %}
63 63
64 {% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a> 64 {% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a>
65 {% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;search={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a> 65 {% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;value={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a>
66 {% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %} 66 {% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;value={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
67 67
68 {% endif %} 68 {% endif %}
69{% endblock %} 69{% endblock %}
diff --git a/themes/baggy/view.twig b/themes/baggy/view.twig
index af97407d..7b65340a 100755
--- a/themes/baggy/view.twig
+++ b/themes/baggy/view.twig
@@ -16,7 +16,7 @@
16 {% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %} 16 {% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %}
17 {% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr icon icon-flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr icon icon-flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span> ({{ flattr.numflattrs }})</a></li>{% endif %}{% endif %} 17 {% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr icon icon-flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr icon icon-flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span> ({{ flattr.numflattrs }})</a></li>{% endif %}{% endif %}
18 {% if constant('SHOW_PRINTLINK') == 1 %}<li><a title="{% trans "Print" %}" class="tool icon icon-print" href="javascript: window.print();"><span>{% trans "Print" %}</span></a></li>{% endif %} 18 {% if constant('SHOW_PRINTLINK') == 1 %}<li><a title="{% trans "Print" %}" class="tool icon icon-print" href="javascript: window.print();"><span>{% trans "Print" %}</span></a></li>{% endif %}
19 <li><a href="./?epub&amp;method=id&amp;id={{ entry.id|e }}" title="Generate epub file">EPUB</a></li> 19 <li><a href="./?epub&amp;method=id&amp;value={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
20 <li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "Does this article appear wrong?" %}" class="tool bad-display icon icon-delete"><span>{% trans "Does this article appear wrong?" %}</span></a></li> 20 <li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "Does this article appear wrong?" %}" class="tool bad-display icon icon-delete"><span>{% trans "Does this article appear wrong?" %}</span></a></li>
21 </ul> 21 </ul>
22 </div> 22 </div>
diff --git a/themes/courgette/_view.twig b/themes/courgette/_view.twig
index 25479a3d..c5c916c0 100755
--- a/themes/courgette/_view.twig
+++ b/themes/courgette/_view.twig
@@ -12,7 +12,7 @@
12 {% if constant('SHARE_MAIL') == 1 %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email" title="{% trans "email" %}"><span>{% trans "email" %}</span></a></li>{% endif %} 12 {% if constant('SHARE_MAIL') == 1 %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email" title="{% trans "email" %}"><span>{% trans "email" %}</span></a></li>{% endif %}
13 {% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %} 13 {% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %}
14 {% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li class="flattrli"><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span>{{ flattr.numflattrs }}</a></li>{% endif %}{% endif %} 14 {% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li class="flattrli"><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span>{{ flattr.numflattrs }}</a></li>{% endif %}{% endif %}
15 <li><a href="./?epub&amp;method=id&amp;id={{ entry.id|e }}" title="Generate epub file">EPUB</a></li> 15 <li><a href="./?epub&amp;method=id&amp;value={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
16 <li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "this article appears wrong?" %}" class="tool bad-display"><span>{% trans "this article appears wrong?" %}</span></a></li> 16 <li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "this article appears wrong?" %}" class="tool bad-display"><span>{% trans "this article appears wrong?" %}</span></a></li>
17 </ul> 17 </ul>
18 </div> 18 </div>
diff --git a/themes/courgette/home.twig b/themes/courgette/home.twig
index 401f3f20..811298eb 100755
--- a/themes/courgette/home.twig
+++ b/themes/courgette/home.twig
@@ -53,9 +53,9 @@
53 53
54 {{ block('pager') }} 54 {{ block('pager') }}
55 55
56 {% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a> 56 {% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a>
57 {% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;search={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a> 57 {% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;value={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a>
58 {% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %} 58 {% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;value={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
59 59
60 {% endif %} 60 {% endif %}
61 61
diff --git a/themes/default/home.twig b/themes/default/home.twig
index e6c781f5..093c2dc5 100755
--- a/themes/default/home.twig
+++ b/themes/default/home.twig
@@ -60,9 +60,9 @@
60 60
61 {% if view == 'home' %}{% if nb_results > 1 %}<a title="{% trans "mark all the entries as read" %}" href="./?action=archive_all">{% trans "mark all the entries as read" %}</a>{% endif %}{% endif %} 61 {% if view == 'home' %}{% if nb_results > 1 %}<a title="{% trans "mark all the entries as read" %}" href="./?action=archive_all">{% trans "mark all the entries as read" %}</a>{% endif %}{% endif %}
62 62
63 {% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a> 63 {% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a>
64 {% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;search={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a> 64 {% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;value={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a>
65 {% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %} 65 {% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;value={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
66 66
67 {% endif %} 67 {% endif %}
68{% endblock %} 68{% endblock %}
diff --git a/themes/default/view.twig b/themes/default/view.twig
index b7d48c00..90b11839 100755
--- a/themes/default/view.twig
+++ b/themes/default/view.twig
@@ -15,7 +15,7 @@
15 {% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %} 15 {% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %}
16 {% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span>{{ flattr.numflattrs }}</a></li>{% endif %}{% endif %} 16 {% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span>{{ flattr.numflattrs }}</a></li>{% endif %}{% endif %}
17 {% if constant('SHOW_PRINTLINK') == 1 %}<li><a title="{% trans "Print" %}" class="tool print" href="javascript: window.print();"><span>{% trans "Print" %}</span></a></li>{% endif %} 17 {% if constant('SHOW_PRINTLINK') == 1 %}<li><a title="{% trans "Print" %}" class="tool print" href="javascript: window.print();"><span>{% trans "Print" %}</span></a></li>{% endif %}
18 <li><a href="./?epub&amp;method=id&amp;id={{ entry.id|e }}" title="Generate epub file">EPUB</a></li> 18 <li><a href="./?epub&amp;method=id&amp;value={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
19 <li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "Does this article appear wrong?" %}" class="tool bad-display"><span>{% trans "Does this article appear wrong?" %}</span></a></li> 19 <li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "Does this article appear wrong?" %}" class="tool bad-display"><span>{% trans "Does this article appear wrong?" %}</span></a></li>
20 {% if constant('SHOW_READPERCENT') == 1 %}<li><div id="readLeftPercent">0%</div></li>{% endif %} 20 {% if constant('SHOW_READPERCENT') == 1 %}<li><div id="readLeftPercent">0%</div></li>{% endif %}
21 </ul> 21 </ul>