aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Lœuillet <nicolas.loeuillet@gmail.com>2013-08-04 20:58:31 +0200
committerNicolas Lœuillet <nicolas.loeuillet@gmail.com>2013-08-04 20:58:31 +0200
commiteb1af592194e225bf887e4893e697f0ab8dd9a26 (patch)
tree4ca66f2328ac5ab2abac1cfae98a0e1a7c4e5583
parent3ba5f81b7bc99d7ff954aa5b76aca93c9e157e67 (diff)
downloadwallabag-eb1af592194e225bf887e4893e697f0ab8dd9a26.tar.gz
wallabag-eb1af592194e225bf887e4893e697f0ab8dd9a26.tar.zst
wallabag-eb1af592194e225bf887e4893e697f0ab8dd9a26.zip
refactoring
-rw-r--r--inc/config.php79
-rw-r--r--inc/poche/Poche.class.php176
-rw-r--r--inc/poche/Tools.class.php208
-rw-r--r--inc/poche/Url.class.php94
-rw-r--r--inc/poche/config.inc.php40
-rw-r--r--inc/poche/pocheCore.php269
-rw-r--r--inc/poche/pochePictures.php2
-rw-r--r--inc/poche/pocheTools.class.php126
-rw-r--r--inc/store/sqlite.class.php2
-rw-r--r--index.php45
-rw-r--r--tpl/config.twig2
11 files changed, 544 insertions, 499 deletions
diff --git a/inc/config.php b/inc/config.php
deleted file mode 100644
index 495dbb85..00000000
--- a/inc/config.php
+++ /dev/null
@@ -1,79 +0,0 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <nicolas@loeuillet.org>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11define ('POCHE_VERSION', '0.3');
12define ('MODE_DEMO', FALSE);
13define ('DEBUG_POCHE', FALSE);
14define ('CONVERT_LINKS_FOOTNOTES', FALSE);
15define ('REVERT_FORCED_PARAGRAPH_ELEMENTS', FALSE);
16define ('DOWNLOAD_PICTURES', FALSE);
17define ('SALT', '464v54gLLw928uz4zUBqkRJeiPY68zCX');
18define ('ABS_PATH', 'assets/');
19define ('TPL', './tpl');
20define ('LOCALE', './locale');
21define ('CACHE', './cache');
22define ('LANG', 'fr_FR.UTF8');
23
24$storage_type = 'sqlite'; # sqlite, file
25
26# /!\ Be careful if you change the lines below /!\
27require_once 'poche/pocheTools.class.php';
28require_once 'poche/pocheCore.php';
29require_once '3rdparty/Readability.php';
30require_once '3rdparty/Encoding.php';
31require_once '3rdparty/Session.class.php';
32require_once 'store/store.class.php';
33require_once 'store/' . $storage_type . '.class.php';
34require_once './vendor/autoload.php';
35
36if (DOWNLOAD_PICTURES) {
37 require_once 'poche/pochePicture.php';
38}
39
40# i18n
41putenv('LC_ALL=' . LANG);
42setlocale(LC_ALL, LANG);
43bindtextdomain(LANG, LOCALE);
44textdomain(LANG);
45
46# template engine
47// Twig_Autoloader::register();
48$loader = new Twig_Loader_Filesystem(TPL);
49$twig = new Twig_Environment($loader, array(
50 'cache' => CACHE,
51));
52$twig->addExtension(new Twig_Extensions_Extension_I18n());
53
54Session::init();
55$store = new $storage_type();
56
57# installation
58if(!$store->isInstalled())
59{
60 pocheTools::logm('poche still not installed');
61 echo $twig->render('install.twig', array(
62 'token' => Session::getToken(),
63 ));
64 if (isset($_GET['install'])) {
65 if (($_POST['password'] == $_POST['password_repeat'])
66 && $_POST['password'] != "" && $_POST['login'] != "") {
67 # let's rock, install poche baby !
68 $store->install($_POST['login'], encode_string($_POST['password'] . $_POST['login']));
69 Session::logout();
70 pocheTools::redirect();
71 }
72 }
73 exit();
74}
75
76$_SESSION['login'] = (isset ($_SESSION['login'])) ? $_SESSION['login'] : $store->getLogin();
77$_SESSION['pass'] = (isset ($_SESSION['pass'])) ? $_SESSION['pass'] : $store->getPassword();
78
79pocheTools::initPhp(); \ No newline at end of file
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php
new file mode 100644
index 00000000..973ae3e2
--- /dev/null
+++ b/inc/poche/Poche.class.php
@@ -0,0 +1,176 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <support@inthepoche.com>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11class Poche
12{
13 public $store;
14 public $tpl;
15
16 function __construct($storage_type)
17 {
18 $this->store = new $storage_type();
19 $this->init();
20
21 # installation
22 if(!$this->store->isInstalled())
23 {
24 $this->install();
25 }
26
27 $this->saveUser();
28 }
29
30 private function init()
31 {
32 # l10n
33 putenv('LC_ALL=' . LANG);
34 setlocale(LC_ALL, LANG);
35 bindtextdomain(LANG, LOCALE);
36 textdomain(LANG);
37
38 # template engine
39 $loader = new Twig_Loader_Filesystem(TPL);
40 $this->tpl = new Twig_Environment($loader, array(
41 'cache' => CACHE,
42 ));
43 $this->tpl->addExtension(new Twig_Extensions_Extension_I18n());
44
45 Tools::initPhp();
46 Session::init();
47 }
48
49 private function install()
50 {
51 Tools::logm('poche still not installed');
52 echo $this->tpl->render('install.twig', array(
53 'token' => Session::getToken(),
54 ));
55 if (isset($_GET['install'])) {
56 if (($_POST['password'] == $_POST['password_repeat'])
57 && $_POST['password'] != "" && $_POST['login'] != "") {
58 # let's rock, install poche baby !
59 $this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']));
60 Session::logout();
61 Tools::redirect();
62 }
63 }
64 exit();
65 }
66
67 private function saveUser()
68 {
69 $_SESSION['login'] = (isset ($_SESSION['login'])) ? $_SESSION['login'] : $this->store->getLogin();
70 $_SESSION['pass'] = (isset ($_SESSION['pass'])) ? $_SESSION['pass'] : $this->store->getPassword();
71 }
72
73 /**
74 * Call action (mark as fav, archive, delete, etc.)
75 */
76 public function action($action, Url $url, $id)
77 {
78 switch ($action)
79 {
80 case 'add':
81 if($parametres_url = $url->fetchContent()) {
82 if ($this->store->add($url->getUrl(), $parametres_url['title'], $parametres_url['content'])) {
83 Tools::logm('add link ' . $url->getUrl());
84 $last_id = $this->store->getLastId();
85 if (DOWNLOAD_PICTURES) {
86 $content = filtre_picture($parametres_url['content'], $url->getUrl(), $last_id);
87 }
88 #$msg->add('s', _('the link has been added successfully'));
89 }
90 else {
91 #$msg->add('e', _('error during insertion : the link wasn\'t added'));
92 Tools::logm('error during insertion : the link wasn\'t added');
93 }
94 }
95 else {
96 #$msg->add('e', _('error during url preparation : the link wasn\'t added'));
97 Tools::logm('error during content fetch');
98 }
99 break;
100 case 'delete':
101 if ($this->store->deleteById($id)) {
102 if (DOWNLOAD_PICTURES) {
103 remove_directory(ABS_PATH . $id);
104 }
105 #$msg->add('s', _('the link has been deleted successfully'));
106 Tools::logm('delete link #' . $id);
107 }
108 else {
109 #$msg->add('e', _('the link wasn\'t deleted'));
110 Tools::logm('error : can\'t delete link #' . $id);
111 }
112 break;
113 case 'toggle_fav' :
114 $this->store->favoriteById($id);
115 Tools::logm('mark as favorite link #' . $id);
116 break;
117 case 'toggle_archive' :
118 $this->store->archiveById($id);
119 Tools::logm('archive link #' . $id);
120 break;
121 default:
122 break;
123 }
124 }
125
126 function displayView($view, $id = 0)
127 {
128 $tpl_vars = array();
129
130 switch ($view)
131 {
132 case 'install':
133 Tools::logm('install mode');
134 break;
135 case 'import';
136 Tools::logm('import mode');
137 break;
138 case 'export':
139 $entries = $this->store->retrieveAll();
140 // $tpl->assign('export', Tools::renderJson($entries));
141 // $tpl->draw('export');
142 Tools::logm('export view');
143 break;
144 case 'config':
145 Tools::logm('config view');
146 break;
147 case 'view':
148 $entry = $this->store->retrieveOneById($id);
149 if ($entry != NULL) {
150 Tools::logm('view link #' . $id);
151 $content = $entry['content'];
152 if (function_exists('tidy_parse_string')) {
153 $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8');
154 $tidy->cleanRepair();
155 $content = $tidy->value;
156 }
157 $tpl_vars = array(
158 'entry' => $entry,
159 'content' => $content,
160 );
161 }
162 else {
163 Tools::logm('error in view call : entry is NULL');
164 }
165 break;
166 default: # home view
167 $entries = $this->store->getEntriesByView($view);
168 $tpl_vars = array(
169 'entries' => $entries,
170 );
171 break;
172 }
173
174 return $tpl_vars;
175 }
176} \ No newline at end of file
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php
new file mode 100644
index 00000000..c277035f
--- /dev/null
+++ b/inc/poche/Tools.class.php
@@ -0,0 +1,208 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <support@inthepoche.com>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11class Tools
12{
13 public static function initPhp()
14 {
15 define('START_TIME', microtime(true));
16
17 if (phpversion() < 5) {
18 die(_('Oops, it seems you don\'t have PHP 5.'));
19 }
20
21 error_reporting(E_ALL);
22
23 function stripslashesDeep($value) {
24 return is_array($value)
25 ? array_map('stripslashesDeep', $value)
26 : stripslashes($value);
27 }
28
29 if (get_magic_quotes_gpc()) {
30 $_POST = array_map('stripslashesDeep', $_POST);
31 $_GET = array_map('stripslashesDeep', $_GET);
32 $_COOKIE = array_map('stripslashesDeep', $_COOKIE);
33 }
34
35 ob_start();
36 register_shutdown_function('ob_end_flush');
37 }
38
39 public static function getPocheUrl()
40 {
41 $https = (!empty($_SERVER['HTTPS'])
42 && (strtolower($_SERVER['HTTPS']) == 'on'))
43 || (isset($_SERVER["SERVER_PORT"])
44 && $_SERVER["SERVER_PORT"] == '443'); // HTTPS detection.
45 $serverport = (!isset($_SERVER["SERVER_PORT"])
46 || $_SERVER["SERVER_PORT"] == '80'
47 || ($https && $_SERVER["SERVER_PORT"] == '443')
48 ? '' : ':' . $_SERVER["SERVER_PORT"]);
49
50 $scriptname = str_replace('/index.php', '/', $_SERVER["SCRIPT_NAME"]);
51
52 if (!isset($_SERVER["SERVER_NAME"])) {
53 return $scriptname;
54 }
55
56 return 'http' . ($https ? 's' : '') . '://'
57 . $_SERVER["SERVER_NAME"] . $serverport . $scriptname;
58 }
59
60 public static function redirect($url = '')
61 {
62 if ($url === '') {
63 $url = (empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']);
64 if (isset($_POST['returnurl'])) {
65 $url = $_POST['returnurl'];
66 }
67 }
68
69 # prevent loop
70 if (empty($url) || parse_url($url, PHP_URL_QUERY) === $_SERVER['QUERY_STRING']) {
71 $url = Tools::getPocheUrl();
72 }
73
74 if (substr($url, 0, 1) !== '?') {
75 $ref = Tools::getPocheUrl();
76 if (substr($url, 0, strlen($ref)) !== $ref) {
77 $url = $ref;
78 }
79 }
80 header('Location: '.$url);
81 exit();
82 }
83
84 public static function getTplFile($view)
85 {
86 $tpl_file = 'home.twig';
87 switch ($view)
88 {
89 case 'install':
90 $tpl_file = 'install.twig';
91 break;
92 case 'import';
93 $tpl_file = 'import.twig';
94 break;
95 case 'export':
96 $tpl_file = 'export.twig';
97 break;
98 case 'config':
99 $tpl_file = 'config.twig';
100 break;
101 case 'view':
102 $tpl_file = 'view.twig';
103 break;
104 default:
105 break;
106 }
107 return $tpl_file;
108 }
109
110 public static function getFile($url)
111 {
112 $timeout = 15;
113 $useragent = "Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0";
114
115 if (in_array ('curl', get_loaded_extensions())) {
116 # Fetch feed from URL
117 $curl = curl_init();
118 curl_setopt($curl, CURLOPT_URL, $url);
119 curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
120 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
121 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
122 curl_setopt($curl, CURLOPT_HEADER, false);
123
124 # for ssl, do not verified certificate
125 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
126 curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE );
127
128 # FeedBurner requires a proper USER-AGENT...
129 curl_setopt($curl, CURL_HTTP_VERSION_1_1, true);
130 curl_setopt($curl, CURLOPT_ENCODING, "gzip, deflate");
131 curl_setopt($curl, CURLOPT_USERAGENT, $useragent);
132
133 $data = curl_exec($curl);
134 $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
135 $httpcodeOK = isset($httpcode) and ($httpcode == 200 or $httpcode == 301);
136 curl_close($curl);
137 } else {
138 # create http context and add timeout and user-agent
139 $context = stream_context_create(
140 array(
141 'http' => array(
142 'timeout' => $timeout,
143 'header' => "User-Agent: " . $useragent,
144 'follow_location' => true
145 ),
146 'ssl' => array(
147 'verify_peer' => false,
148 'allow_self_signed' => true
149 )
150 )
151 );
152
153 # only download page lesser than 4MB
154 $data = @file_get_contents($url, false, $context, -1, 4000000);
155
156 if (isset($http_response_header) and isset($http_response_header[0])) {
157 $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));
158 }
159 }
160
161 # if response is not empty and response is OK
162 if (isset($data) and isset($httpcodeOK) and $httpcodeOK) {
163
164 # take charset of page and get it
165 preg_match('#<meta .*charset=.*>#Usi', $data, $meta);
166
167 # if meta tag is found
168 if (!empty($meta[0])) {
169 preg_match('#charset="?(.*)"#si', $meta[0], $encoding);
170 # if charset is found set it otherwise, set it to utf-8
171 $html_charset = (!empty($encoding[1])) ? strtolower($encoding[1]) : 'utf-8';
172 } else {
173 $html_charset = 'utf-8';
174 $encoding[1] = '';
175 }
176
177 # replace charset of url to charset of page
178 $data = str_replace('charset=' . $encoding[1], 'charset=' . $html_charset, $data);
179
180 return $data;
181 }
182 else {
183 return FALSE;
184 }
185 }
186
187 public static function renderJson($data)
188 {
189 header('Cache-Control: no-cache, must-revalidate');
190 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
191 header('Content-type: application/json; charset=UTF-8');
192 echo json_encode($data);
193 exit();
194 }
195
196 public static function logm($message)
197 {
198 if (DEBUG_POCHE) {
199 $t = strval(date('Y/m/d_H:i:s')) . ' - ' . $_SERVER["REMOTE_ADDR"] . ' - ' . strval($message) . "\n";
200 file_put_contents('./log.txt', $t, FILE_APPEND);
201 }
202 }
203
204 public static function encodeString($string)
205 {
206 return sha1($string . SALT);
207 }
208} \ No newline at end of file
diff --git a/inc/poche/Url.class.php b/inc/poche/Url.class.php
new file mode 100644
index 00000000..f4a8f99e
--- /dev/null
+++ b/inc/poche/Url.class.php
@@ -0,0 +1,94 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <support@inthepoche.com>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11class Url
12{
13 public $url;
14
15 function __construct($url)
16 {
17 $this->url = base64_decode($url);
18 }
19
20 public function getUrl() {
21 return $this->url;
22 }
23
24 public function setUrl($url) {
25 $this->url = $url;
26 }
27
28 public function isCorrect()
29 {
30 $pattern = '|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i';
31
32 return preg_match($pattern, $this->url);
33 }
34
35 public function clean()
36 {
37 $url = html_entity_decode(trim($this->url));
38
39 $stuff = strpos($url,'&utm_source=');
40 if ($stuff !== FALSE)
41 $url = substr($url, 0, $stuff);
42 $stuff = strpos($url,'?utm_source=');
43 if ($stuff !== FALSE)
44 $url = substr($url, 0, $stuff);
45 $stuff = strpos($url,'#xtor=RSS-');
46 if ($stuff !== FALSE)
47 $url = substr($url, 0, $stuff);
48
49 $this->url = $url;
50 }
51
52 public function fetchContent()
53 {
54 if ($this->isCorrect()) {
55 $this->clean();
56 $html = Encoding::toUTF8(Tools::getFile($this->getUrl()));
57
58 # if Tools::getFile() if not able to retrieve HTTPS content, try the same URL with HTTP protocol
59 if (!preg_match('!^https?://!i', $this->getUrl()) && (!isset($html) || strlen($html) <= 0)) {
60 $this->setUrl('http://' . $this->getUrl());
61 $html = Encoding::toUTF8(Tools::getFile($this->getUrl()));
62 }
63
64 if (function_exists('tidy_parse_string')) {
65 $tidy = tidy_parse_string($html, array(), 'UTF8');
66 $tidy->cleanRepair();
67 $html = $tidy->value;
68 }
69
70 $parameters = array();
71 if (isset($html) and strlen($html) > 0)
72 {
73 $readability = new Readability($html, $this->getUrl());
74 $readability->convertLinksToFootnotes = CONVERT_LINKS_FOOTNOTES;
75 $readability->revertForcedParagraphElements = REVERT_FORCED_PARAGRAPH_ELEMENTS;
76
77 if($readability->init())
78 {
79 $content = $readability->articleContent->innerHTML;
80 $parameters['title'] = $readability->articleTitle->innerHTML;
81 $parameters['content'] = $content;
82
83 return $parameters;
84 }
85 }
86 }
87 else {
88 #$msg->add('e', _('error during url preparation : the link is not valid'));
89 Tools::logm($this->getUrl() . ' is not a valid url');
90 }
91
92 return FALSE;
93 }
94} \ No newline at end of file
diff --git a/inc/poche/config.inc.php b/inc/poche/config.inc.php
new file mode 100644
index 00000000..81297e0c
--- /dev/null
+++ b/inc/poche/config.inc.php
@@ -0,0 +1,40 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <nicolas@loeuillet.org>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11define ('POCHE_VERSION', '0.4');
12define ('MODE_DEMO', FALSE);
13define ('DEBUG_POCHE', FALSE);
14define ('CONVERT_LINKS_FOOTNOTES', FALSE);
15define ('REVERT_FORCED_PARAGRAPH_ELEMENTS', FALSE);
16define ('DOWNLOAD_PICTURES', FALSE);
17define ('SALT', '464v54gLLw928uz4zUBqkRJeiPY68zCX');
18define ('ABS_PATH', 'assets/');
19define ('TPL', './tpl');
20define ('LOCALE', './locale');
21define ('CACHE', './cache');
22define ('LANG', 'fr_FR.UTF8');
23$storage_type = 'sqlite'; # sqlite, file
24
25# /!\ Be careful if you change the lines below /!\
26require_once './inc/poche/Tools.class.php';
27require_once './inc/poche/Url.class.php';
28require_once './inc/poche/Poche.class.php';
29require_once './inc/3rdparty/Readability.php';
30require_once './inc/3rdparty/Encoding.php';
31require_once './inc/3rdparty/Session.class.php';
32require_once './inc/store/store.class.php';
33require_once './inc/store/' . $storage_type . '.class.php';
34require_once './vendor/autoload.php';
35
36if (DOWNLOAD_PICTURES) {
37 require_once './inc/poche/pochePicture.php';
38}
39
40$poche = new Poche($storage_type); \ No newline at end of file
diff --git a/inc/poche/pocheCore.php b/inc/poche/pocheCore.php
deleted file mode 100644
index 74b063e4..00000000
--- a/inc/poche/pocheCore.php
+++ /dev/null
@@ -1,269 +0,0 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <support@inthepoche.com>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11function encode_string($string)
12{
13 return sha1($string . SALT);
14}
15
16function get_external_file($url)
17{
18 $timeout = 15;
19 $useragent = "Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0";
20
21 if (in_array ('curl', get_loaded_extensions())) {
22 # Fetch feed from URL
23 $curl = curl_init();
24 curl_setopt($curl, CURLOPT_URL, $url);
25 curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
26 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
27 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
28 curl_setopt($curl, CURLOPT_HEADER, false);
29
30 # for ssl, do not verified certificate
31 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
32 curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE );
33
34 # FeedBurner requires a proper USER-AGENT...
35 curl_setopt($curl, CURL_HTTP_VERSION_1_1, true);
36 curl_setopt($curl, CURLOPT_ENCODING, "gzip, deflate");
37 curl_setopt($curl, CURLOPT_USERAGENT, $useragent);
38
39 $data = curl_exec($curl);
40 $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
41 $httpcodeOK = isset($httpcode) and ($httpcode == 200 or $httpcode == 301);
42 curl_close($curl);
43 } else {
44 # create http context and add timeout and user-agent
45 $context = stream_context_create(
46 array(
47 'http' => array(
48 'timeout' => $timeout,
49 'header' => "User-Agent: " . $useragent,
50 'follow_location' => true
51 ),
52 'ssl' => array(
53 'verify_peer' => false,
54 'allow_self_signed' => true
55 )
56 )
57 );
58
59 # only download page lesser than 4MB
60 $data = @file_get_contents($url, false, $context, -1, 4000000);
61
62 if (isset($http_response_header) and isset($http_response_header[0])) {
63 $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));
64 }
65 }
66
67 # if response is not empty and response is OK
68 if (isset($data) and isset($httpcodeOK) and $httpcodeOK) {
69
70 # take charset of page and get it
71 preg_match('#<meta .*charset=.*>#Usi', $data, $meta);
72
73 # if meta tag is found
74 if (!empty($meta[0])) {
75 preg_match('#charset="?(.*)"#si', $meta[0], $encoding);
76 # if charset is found set it otherwise, set it to utf-8
77 $html_charset = (!empty($encoding[1])) ? strtolower($encoding[1]) : 'utf-8';
78 } else {
79 $html_charset = 'utf-8';
80 $encoding[1] = '';
81 }
82
83 # replace charset of url to charset of page
84 $data = str_replace('charset=' . $encoding[1], 'charset=' . $html_charset, $data);
85
86 return $data;
87 }
88 else {
89 return FALSE;
90 }
91}
92
93function fetch_url_content($url)
94{
95 $url = base64_decode($url);
96 if (pocheTools::isUrl($url)) {
97 $url = pocheTools::cleanURL($url);
98 $html = Encoding::toUTF8(get_external_file($url));
99
100 # if get_external_file if not able to retrieve HTTPS content, try the same URL with HTTP protocol
101 if (!preg_match('!^https?://!i', $url) && (!isset($html) || strlen($html) <= 0)) {
102 $url = 'http://' . $url;
103 $html = Encoding::toUTF8(get_external_file($url));
104 }
105
106 if (function_exists('tidy_parse_string')) {
107 $tidy = tidy_parse_string($html, array(), 'UTF8');
108 $tidy->cleanRepair();
109 $html = $tidy->value;
110 }
111
112 $parameters = array();
113 if (isset($html) and strlen($html) > 0)
114 {
115 $readability = new Readability($html, $url);
116 $readability->convertLinksToFootnotes = CONVERT_LINKS_FOOTNOTES;
117 $readability->revertForcedParagraphElements = REVERT_FORCED_PARAGRAPH_ELEMENTS;
118
119 if($readability->init())
120 {
121 $content = $readability->articleContent->innerHTML;
122 $parameters['title'] = $readability->articleTitle->innerHTML;
123 $parameters['content'] = $content;
124
125 return $parameters;
126 }
127 }
128 }
129 else {
130 #$msg->add('e', _('error during url preparation : the link is not valid'));
131 pocheTools::logm($url . ' is not a valid url');
132 }
133
134 return FALSE;
135}
136
137function get_tpl_file($view)
138{
139 $tpl_file = 'home.twig';
140 switch ($view)
141 {
142 case 'install':
143 $tpl_file = 'install.twig';
144 break;
145 case 'import';
146 $tpl_file = 'import.twig';
147 break;
148 case 'export':
149 $tpl_file = 'export.twig';
150 break;
151 case 'config':
152 $tpl_file = 'config.twig';
153 break;
154 case 'view':
155 $tpl_file = 'view.twig';
156 break;
157 default:
158 break;
159 }
160 return $tpl_file;
161}
162
163function display_view($view, $id = 0)
164{
165 global $store;
166
167 $tpl_vars = array();
168
169 switch ($view)
170 {
171 case 'install':
172 pocheTools::logm('install mode');
173 break;
174 case 'import';
175 pocheTools::logm('import mode');
176 break;
177 case 'export':
178 $entries = $store->retrieveAll();
179 $tpl->assign('export', pocheTools::renderJson($entries));
180 $tpl->draw('export');
181 pocheTools::logm('export view');
182 break;
183 case 'config':
184 pocheTools::logm('config view');
185 break;
186 case 'view':
187 $entry = $store->retrieveOneById($id);
188 if ($entry != NULL) {
189 pocheTools::logm('view link #' . $id);
190 $content = $entry['content'];
191 if (function_exists('tidy_parse_string')) {
192 $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8');
193 $tidy->cleanRepair();
194 $content = $tidy->value;
195 }
196 $tpl_vars = array(
197 'entry' => $entry,
198 'content' => $content,
199 );
200 }
201 else {
202 pocheTools::logm('error in view call : entry is NULL');
203 }
204 break;
205 default: # home view
206 $entries = $store->getEntriesByView($view);
207 $tpl_vars = array(
208 'entries' => $entries,
209 );
210 break;
211 }
212
213 return $tpl_vars;
214}
215
216/**
217 * Call action (mark as fav, archive, delete, etc.)
218 */
219function action_to_do($action, $url, $id = 0)
220{
221 global $store;
222
223 switch ($action)
224 {
225 case 'add':
226 if($parametres_url = fetch_url_content($url)) {
227 if ($store->add($url, $parametres_url['title'], $parametres_url['content'])) {
228 pocheTools::logm('add link ' . $url);
229 $last_id = $store->getLastId();
230 if (DOWNLOAD_PICTURES) {
231 $content = filtre_picture($parametres_url['content'], $url, $last_id);
232 }
233 #$msg->add('s', _('the link has been added successfully'));
234 }
235 else {
236 #$msg->add('e', _('error during insertion : the link wasn\'t added'));
237 pocheTools::logm('error during insertion : the link wasn\'t added');
238 }
239 }
240 else {
241 #$msg->add('e', _('error during url preparation : the link wasn\'t added'));
242 pocheTools::logm('error during content fetch');
243 }
244 break;
245 case 'delete':
246 if ($store->deleteById($id)) {
247 if (DOWNLOAD_PICTURES) {
248 remove_directory(ABS_PATH . $id);
249 }
250 #$msg->add('s', _('the link has been deleted successfully'));
251 pocheTools::logm('delete link #' . $id);
252 }
253 else {
254 #$msg->add('e', _('the link wasn\'t deleted'));
255 pocheTools::logm('error : can\'t delete link #' . $id);
256 }
257 break;
258 case 'toggle_fav' :
259 $store->favoriteById($id);
260 pocheTools::logm('mark as favorite link #' . $id);
261 break;
262 case 'toggle_archive' :
263 $store->archiveById($id);
264 pocheTools::logm('archive link #' . $id);
265 break;
266 default:
267 break;
268 }
269}
diff --git a/inc/poche/pochePictures.php b/inc/poche/pochePictures.php
index 0d73a149..4e4a0b08 100644
--- a/inc/poche/pochePictures.php
+++ b/inc/poche/pochePictures.php
@@ -67,7 +67,7 @@ function get_absolute_link($relative_link, $url) {
67 */ 67 */
68function download_pictures($absolute_path, $fullpath) 68function download_pictures($absolute_path, $fullpath)
69{ 69{
70 $rawdata = get_external_file($absolute_path); 70 $rawdata = Tools::getFile($absolute_path);
71 71
72 if(file_exists($fullpath)) { 72 if(file_exists($fullpath)) {
73 unlink($fullpath); 73 unlink($fullpath);
diff --git a/inc/poche/pocheTools.class.php b/inc/poche/pocheTools.class.php
deleted file mode 100644
index 08c9dc8f..00000000
--- a/inc/poche/pocheTools.class.php
+++ /dev/null
@@ -1,126 +0,0 @@
1<?php
2/**
3 * poche, a read it later open source system
4 *
5 * @category poche
6 * @author Nicolas Lœuillet <support@inthepoche.com>
7 * @copyright 2013
8 * @license http://www.wtfpl.net/ see COPYING file
9 */
10
11class pocheTools
12{
13 public static function initPhp()
14 {
15 define('START_TIME', microtime(true));
16
17 if (phpversion() < 5) {
18 die(_('Oops, it seems you don\'t have PHP 5.'));
19 }
20
21 error_reporting(E_ALL);
22
23 function stripslashesDeep($value) {
24 return is_array($value)
25 ? array_map('stripslashesDeep', $value)
26 : stripslashes($value);
27 }
28
29 if (get_magic_quotes_gpc()) {
30 $_POST = array_map('stripslashesDeep', $_POST);
31 $_GET = array_map('stripslashesDeep', $_GET);
32 $_COOKIE = array_map('stripslashesDeep', $_COOKIE);
33 }
34
35 ob_start();
36 register_shutdown_function('ob_end_flush');
37 }
38
39 public static function isUrl($url)
40 {
41 $pattern = '|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i';
42
43 return preg_match($pattern, $url);
44 }
45
46 public static function getUrl()
47 {
48 $https = (!empty($_SERVER['HTTPS'])
49 && (strtolower($_SERVER['HTTPS']) == 'on'))
50 || (isset($_SERVER["SERVER_PORT"])
51 && $_SERVER["SERVER_PORT"] == '443'); // HTTPS detection.
52 $serverport = (!isset($_SERVER["SERVER_PORT"])
53 || $_SERVER["SERVER_PORT"] == '80'
54 || ($https && $_SERVER["SERVER_PORT"] == '443')
55 ? '' : ':' . $_SERVER["SERVER_PORT"]);
56
57 $scriptname = str_replace('/index.php', '/', $_SERVER["SCRIPT_NAME"]);
58
59 if (!isset($_SERVER["SERVER_NAME"])) {
60 return $scriptname;
61 }
62
63 return 'http' . ($https ? 's' : '') . '://'
64 . $_SERVER["SERVER_NAME"] . $serverport . $scriptname;
65 }
66
67 public static function redirect($url = '')
68 {
69 if ($url === '') {
70 $url = (empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']);
71 if (isset($_POST['returnurl'])) {
72 $url = $_POST['returnurl'];
73 }
74 }
75
76 # prevent loop
77 if (empty($url) || parse_url($url, PHP_URL_QUERY) === $_SERVER['QUERY_STRING']) {
78 $url = pocheTools::getUrl();
79 }
80
81 if (substr($url, 0, 1) !== '?') {
82 $ref = pocheTools::getUrl();
83 if (substr($url, 0, strlen($ref)) !== $ref) {
84 $url = $ref;
85 }
86 }
87 header('Location: '.$url);
88 exit();
89 }
90
91 public static function cleanURL($url)
92 {
93
94 $url = html_entity_decode(trim($url));
95
96 $stuff = strpos($url,'&utm_source=');
97 if ($stuff !== FALSE)
98 $url = substr($url, 0, $stuff);
99 $stuff = strpos($url,'?utm_source=');
100 if ($stuff !== FALSE)
101 $url = substr($url, 0, $stuff);
102 $stuff = strpos($url,'#xtor=RSS-');
103 if ($stuff !== FALSE)
104 $url = substr($url, 0, $stuff);
105
106 return $url;
107 }
108
109 public static function renderJson($data)
110 {
111 header('Cache-Control: no-cache, must-revalidate');
112 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
113 header('Content-type: application/json; charset=UTF-8');
114
115 echo json_encode($data);
116 exit();
117 }
118
119 public static function logm($message)
120 {
121 if (DEBUG_POCHE) {
122 $t = strval(date('Y/m/d_H:i:s')) . ' - ' . $_SERVER["REMOTE_ADDR"] . ' - ' . strval($message) . "\n";
123 file_put_contents('./log.txt', $t, FILE_APPEND);
124 }
125 }
126} \ No newline at end of file
diff --git a/inc/store/sqlite.class.php b/inc/store/sqlite.class.php
index 21081608..a15bc095 100644
--- a/inc/store/sqlite.class.php
+++ b/inc/store/sqlite.class.php
@@ -90,7 +90,7 @@ class Sqlite extends Store {
90 } 90 }
91 catch (Exception $e) 91 catch (Exception $e)
92 { 92 {
93 logm('execute query error : '.$e->getMessage()); 93 Tools::logm('execute query error : '.$e->getMessage());
94 } 94 }
95 } 95 }
96 96
diff --git a/index.php b/index.php
index dc064428..40779698 100644
--- a/index.php
+++ b/index.php
@@ -8,7 +8,7 @@
8 * @license http://www.wtfpl.net/ see COPYING file 8 * @license http://www.wtfpl.net/ see COPYING file
9 */ 9 */
10 10
11include dirname(__FILE__).'/inc/config.php'; 11include dirname(__FILE__).'/inc/poche/config.inc.php';
12 12
13$notices = array(); 13$notices = array();
14 14
@@ -26,9 +26,9 @@ $referer = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'];
26if (isset($_GET['login'])) { 26if (isset($_GET['login'])) {
27 # hello you 27 # hello you
28 if (!empty($_POST['login']) && !empty($_POST['password'])) { 28 if (!empty($_POST['login']) && !empty($_POST['password'])) {
29 if (Session::login($_SESSION['login'], $_SESSION['pass'], $_POST['login'], encode_string($_POST['password'] . $_POST['login']))) { 29 if (Session::login($_SESSION['login'], $_SESSION['pass'], $_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']))) {
30 pocheTools::logm('login successful'); 30 Tools::logm('login successful');
31 $pocheTools[]['value'] = _('login successful'); 31 $notices['value'] = _('login successful');
32 32
33 if (!empty($_POST['longlastingsession'])) { 33 if (!empty($_POST['longlastingsession'])) {
34 $_SESSION['longlastingsession'] = 31536000; 34 $_SESSION['longlastingsession'] = 31536000;
@@ -38,34 +38,34 @@ if (isset($_GET['login'])) {
38 session_set_cookie_params(0); 38 session_set_cookie_params(0);
39 } 39 }
40 session_regenerate_id(true); 40 session_regenerate_id(true);
41 pocheTools::redirect($referer); 41 Tools::redirect($referer);
42 } 42 }
43 pocheTools::logm('login failed'); 43 Tools::logm('login failed');
44 $notices[]['value'] = _('Login failed !'); 44 $notices['value'] = _('Login failed !');
45 pocheTools::redirect(); 45 Tools::redirect();
46 } else { 46 } else {
47 pocheTools::logm('login failed'); 47 Tools::logm('login failed');
48 pocheTools::redirect(); 48 Tools::redirect();
49 } 49 }
50} 50}
51elseif (isset($_GET['logout'])) { 51elseif (isset($_GET['logout'])) {
52 # see you soon ! 52 # see you soon !
53 pocheTools::logm('logout'); 53 Tools::logm('logout');
54 Session::logout(); 54 Session::logout();
55 pocheTools::redirect(); 55 Tools::redirect();
56} 56}
57elseif (isset($_GET['config'])) { 57elseif (isset($_GET['config'])) {
58 # Update password 58 # Update password
59 if (isset($_POST['password']) && isset($_POST['password_repeat'])) { 59 if (isset($_POST['password']) && isset($_POST['password_repeat'])) {
60 if ($_POST['password'] == $_POST['password_repeat'] && $_POST['password'] != "") { 60 if ($_POST['password'] == $_POST['password_repeat'] && $_POST['password'] != "") {
61 if (!MODE_DEMO) { 61 if (!MODE_DEMO) {
62 pocheTools::logm('password updated'); 62 Tools::logm('password updated');
63 $store->updatePassword(encode_string($_POST['password'] . $_SESSION['login'])); 63 $poche->store->updatePassword(Tools::encodeString($_POST['password'] . $_SESSION['login']));
64 Session::logout(); 64 Session::logout();
65 pocheTools::redirect(); 65 Tools::redirect();
66 } 66 }
67 else { 67 else {
68 pocheTools::logm('in demo mode, you can\'t do this'); 68 Tools::logm('in demo mode, you can\'t do this');
69 } 69 }
70 } 70 }
71 } 71 }
@@ -77,12 +77,13 @@ $full_head = (isset ($_REQUEST['full_head'])) ? htmlentities($_REQUEST['full_hea
77$action = (isset ($_REQUEST['action'])) ? htmlentities($_REQUEST['action']) : ''; 77$action = (isset ($_REQUEST['action'])) ? htmlentities($_REQUEST['action']) : '';
78$_SESSION['sort'] = (isset ($_REQUEST['sort'])) ? htmlentities($_REQUEST['sort']) : 'id'; 78$_SESSION['sort'] = (isset ($_REQUEST['sort'])) ? htmlentities($_REQUEST['sort']) : 'id';
79$id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : ''; 79$id = (isset ($_REQUEST['id'])) ? htmlspecialchars($_REQUEST['id']) : '';
80$url = (isset ($_GET['url'])) ? $_GET['url'] : ''; 80
81$url = new Url((isset ($_GET['url'])) ? $_GET['url'] : '');
81 82
82$tpl_vars = array( 83$tpl_vars = array(
83 'referer' => $referer, 84 'referer' => $referer,
84 'view' => $view, 85 'view' => $view,
85 'poche_url' => pocheTools::getUrl(), 86 'poche_url' => Tools::getPocheUrl(),
86 'demo' => MODE_DEMO, 87 'demo' => MODE_DEMO,
87 'title' => _('poche, a read it later open source system'), 88 'title' => _('poche, a read it later open source system'),
88 'token' => Session::getToken(), 89 'token' => Session::getToken(),
@@ -90,12 +91,12 @@ $tpl_vars = array(
90); 91);
91 92
92if (Session::isLogged()) { 93if (Session::isLogged()) {
93 action_to_do($action, $url, $id); 94 $poche->action($action, $url, $id);
94 $tpl_file = get_tpl_file($view); 95 $tpl_file = Tools::getTplFile($view);
95 $tpl_vars = array_merge($tpl_vars, display_view($view, $id)); 96 $tpl_vars = array_merge($tpl_vars, $poche->displayView($view, $id));
96} 97}
97else { 98else {
98 $tpl_file = 'login.twig'; 99 $tpl_file = 'login.twig';
99} 100}
100 101
101echo $twig->render($tpl_file, $tpl_vars); \ No newline at end of file 102echo $poche->tpl->render($tpl_file, $tpl_vars); \ No newline at end of file
diff --git a/tpl/config.twig b/tpl/config.twig
index be2c0454..4e7bb9d4 100644
--- a/tpl/config.twig
+++ b/tpl/config.twig
@@ -15,7 +15,7 @@
15 <h2>{% trans "Bookmarklet" %}</h2> 15 <h2>{% trans "Bookmarklet" %}</h2>
16 <p>{% trans "Thanks to the bookmarklet, you will be able to easily add a link to your poche." %} {% trans "Have a look to this documentation:" %} <a href="http://inthepoche.com/?pages/Documentation" target="_blank">http://inthepoche.com/?pages/Documentation</a>.</p> 16 <p>{% trans "Thanks to the bookmarklet, you will be able to easily add a link to your poche." %} {% trans "Have a look to this documentation:" %} <a href="http://inthepoche.com/?pages/Documentation" target="_blank">http://inthepoche.com/?pages/Documentation</a>.</p>
17 <p>{% trans "Drag & drop this link to your bookmarks bar and have fun with poche." %}</p> 17 <p>{% trans "Drag & drop this link to your bookmarks bar and have fun with poche." %}</p>
18 <p><a ondragend="this.click();" style="cursor: move; border: 1px dashed grey; background: white;" title="i am a bookmarklet, use me !" href="javascript:if(top['bookmarklet-url@inthepoche.com']){top['bookmarklet-url@inthepoche.com'];}else{(function(){var%20url%20=%20location.href%20||%20url;window.open('{$poche_url}?action=add&url='%20+%20btoa(url),'_self');})();void(0);}">{% trans "poche it!" %}</a></p> 18 <p><a ondragend="this.click();" style="cursor: move; border: 1px dashed grey; background: white;" title="i am a bookmarklet, use me !" href="javascript:if(top['bookmarklet-url@inthepoche.com']){top['bookmarklet-url@inthepoche.com'];}else{(function(){var%20url%20=%20location.href%20||%20url;window.open('{{ poche_url }}?action=add&url='%20+%20btoa(url),'_self');})();void(0);}">{% trans "poche it!" %}</a></p>
19 19
20 <h2>{% trans "Change your password" %}</h2> 20 <h2>{% trans "Change your password" %}</h2>
21 <form method="post" action="?config" name="loginform"> 21 <form method="post" action="?config" name="loginform">